2012-01-12 92 views
0

如果我有一個返回一個字符串如下的方法:運行方法的線程,因爲它實在是太慢了

public string ExecuteCommandSync(object command) 
     { 
      string result = ""; 
      try 
      { 
       System.Diagnostics.ProcessStartInfo procStartInfo = 
        new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command); 


       procStartInfo.RedirectStandardOutput = true; 
       procStartInfo.UseShellExecute = false; 

       procStartInfo.CreateNoWindow = true; 

       System.Diagnostics.Process proc = new System.Diagnostics.Process(); 
       proc.StartInfo = procStartInfo; 
       proc.Start(); 

       result = proc.StandardOutput.ReadToEnd(); 

       Console.WriteLine(result); 
      } 
      catch (Exception objException) 
      { 
       MessageBox.Show("error : " + objException.Message); 
      } 

      return result; 
     } 

現在這工作正常爲小數據,但如果我有大量的數據搞得暈頭轉向..

如果我把這個線程將是更快速地爲大數據或至少改善,作爲即時通訊完全新的線程,我不知道如何與線程再次返回結果爲字符串...

能請有人幫忙。

感謝

編輯:

它是運行在Windows 7 基本思路是調用cmd命令和運行命令C#WinForm應用程序... 這是錯誤我從視覺工作室運行時:

The CLR has been unable to transition from COM context 0x8d85c0 to COM context 0x8d8730 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations. 

編輯2 :: 好了她e是我迄今所做

public string ExecuteCommandSync(object command) 
     { 
      string result = ""; 
      try 
      { 

       backgroundWorker1.RunWorkerAsync(command); 
      } 
      catch (Exception objException) 
      { 
       MessageBox.Show("error : " + objException.Message); 
      } 

      return result; 
     } 
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      string result; 
      Thread.Sleep(300); 
      object command = (object)e.Argument; 
      System.Diagnostics.ProcessStartInfo procStartInfo = 
        new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command); 


      procStartInfo.RedirectStandardOutput = true; 
      procStartInfo.UseShellExecute = false; 

      procStartInfo.CreateNoWindow = true; 

      System.Diagnostics.Process proc = new System.Diagnostics.Process(); 
      proc.StartInfo = procStartInfo; 
      proc.Start(); 

      result = proc.StandardOutput.ReadToEnd(); 
     } 

     private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      results = (string)e.Result; 
     } 

,然後我把它用:

string result1 = ExecuteCommandSync(command); 
+2

你需要給我們更多的上下文 - 你在WinForms應用程序,WPF,服務器端運行這個嗎? – 2012-01-12 12:03:26

+0

你想在這裏做什麼? – 2012-01-12 12:04:10

+2

在另一個線程中運行代碼不會減少運行該代碼所需的時間。它只會帶來更好的用戶體驗,因爲程序不會掛起。 – 2012-01-12 12:04:14

回答

2

添加到您的程序:

BackgroundWorker bw = new BackgroundWorker(); 
bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
bw.RunWorkerAsync(); 

而且也:

void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    string result = (string)e.Result; 
    //do what you need with it. 
} 

void bw_DoWork(object sender, DoWorkEventArgs e) 
{ 
    //do your work here 
    e.Result = yourResult; 
} 

而且記住別人所說的話:一個線程將不會運行比非線程程序更快。好處是程序不會「掛起」。

+0

你可以檢查我的代碼編輯2請它不工作我沒有得到結果返回 – Zaki 2012-01-12 13:35:22

+0

@ Sam1'e結果'而不是'DoWork'結尾的'result'。 – ispiro 2012-01-12 13:39:35

+0

@ Sam1此外,當你調用'ExecuteCommandSync'時 - 你得到的結果將永遠是''「'。無論你想用'proc.StandardOutput.ReadToEnd()'的結果做什麼,都應該在'RunWorkerCompleted'方法中完成。 (如果需要,你可以在那裏調用其他方法。)例如:'Text =(string)e.Result;'。 – ispiro 2012-01-12 14:02:02

0

你可以使用一個事件。當你的thead完成後,它會拋出一個事件,並將字符串賦予該事件。

+0

但這會讓它更快,因爲我正在運行這個大數據並獲取CLS錯誤 – Zaki 2012-01-12 12:15:47

4
  result = proc.StandardOutput.ReadToEnd(); 

這是導致您的主UI線程掛起的語句。直到您啓動的進程停止運行,ReadToEnd()調用纔會完成。 「CLR無法從COM上下文切換......」消息只是一個警告,當調試器也發現你的主線程死機時觸發。這是猜測它可能是由死鎖造成的。

線程的確是您的解決方案,只需將此代碼移動到BackgroundWorker的DoWork事件處理程序中即可。閱讀this MSDN page獲取指導。

+0

我創建了一個backgroundworker並將結果分配給它,但仍然掛起,這裏是代碼我做得正確嗎? BackgroundWorker bw = new BackgroundWorker(); bw.RunWorkerAsync(result = proc.StandardOutput.ReadToEnd()); – Zaki 2012-01-12 12:38:10

+0

對,沒有幫助。按照答案中的建議,必須在DoWork事件處理程序中進行ReadToEnd()調用。只需移動所有的代碼。 – 2012-01-12 12:44:14

+0

請檢查編輯2原始文章我已經做到了,但沒有工作 – Zaki 2012-01-12 13:32:55

0

另一個線程不會讓它運行得更快,因爲等待應用程序執行某些操作所花費的時間不受哪個花鍵執行操作的影響。

但是,那不是你的問題,你的問題是的UI線程花費的時間太長。非UI線程可以愉快地花費數年時間來完成某些操作,而不會觸發該錯誤,所以它確實可以解決問題。

另一種方法是不要做ReadToEnd(),而是讀取並處理更小的塊。根據您所調用的程序的性質,可以解決所有問題(如果程序開始快速響應,並且延遲的原因是它發送大量數據以輸出)或者不是(如果程序需要幾分鐘時間發送一個字節,然後你遇到和以前一樣的問題

這兩者可以合併,與被調用程序的標準輸出一次讀取另一個線程塊,並相應更新狀態因爲它去了。