2017-02-10 68 views
1

我試圖在線程運行完成後運行一個函數。我的線程在按下UI按鈕並且線程需要一段時間才能完成時開始。
運行完成後,我想調用一個函數。這是我到目前爲止所嘗試的代碼。當我嘗試運行我的代碼時,線程從不執行,應用程序凍結。任何關於如何解決這個問題的建議都會有幫助。線程運行完畢後運行函數

public bool StartProbe() 
{ 
    if (File.Exists(Path.Combine(ObsProbeFolder, "probePJM.exe"))) 
    { 
     ThreadStart ProbeThreadStart = new ThreadStart(() => 
     // right side of lambda  
      { 
       // does stuff 
      }); 

      ProbeThread = new Thread(ProbeThreadStart); 
      ProbeThread.Priority = ThreadPriority.BelowNormal; 
      ProbeThread.SetApartmentState(ApartmentState.STA); 
      ProbeThread.Start(); 

    } 
    else 
    {      
     return false; 
    } 

    // waiting for thread to finish 
    ProbeThread.Join(); 
    // run a function 
    loadData(); 

    return true; 
} 
+1

爲什麼你將'ProbeThread.Join();'封裝在for循環中? – Madenis

+0

我最初厭倦了沒有for循環,但它仍然給我同樣的問題。所以我用for循環來看它是否會修復,但它沒有。 – Satish

+0

當您在UI線程上執行'someThread.Join();'時,應用程序會凍結,因爲UI線程將阻塞,直到其他線程停止。 – Maarten

回答

0

我會用一個BackgroundWorker:在交替線程

Worker = new BackgroundWorker(); 
      Worker.RunWorkerCompleted += Worker_RunWorkerCompleted; 
      Worker.DoWork += Worker_DoWork; 

      Worker.RunWorkerAsync(new BackgroundArguments() 
      { 
       // arguments 
      }); 

工作:

private void Worker_DoWork(object sender, DoWorkEventArgs e) 
{  
    // do stuff 
} 

返回到UI線程:

private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     // load data or whatever on UI thread 
    } 
+0

爲什麼使用如BackgroundWorker這樣的舊結構,如果您可以使用TPL和/或等待? – VMAtm

+0

使用BackgroundWorker沒有任何問題,特別是對於像用戶描述的單個進程。我同意TPL更適合運行多個進程,但對於單個進程來說,它們實際上是可以互換的。 – mjhouseman

0

不要使用BackgroundWorker - 這是相當的我希望這個老班有一天會被MS稱爲過時的。

正如你所說,你有一個按鈕,創建一個async void事件處理程序的消防和忘記方案。當你檢查一些exe文件時,我假設你正在運行一些Process in background。此外,你不需要一個線程來運行你的過程 - 你加入它,這就是爲什麼UI掛起。

private async void button_Click(object sender, EventArgs e) 
{ 
    // wait for a result from outer process 
    var result = await RunProcessInBackGround(); 
    //do whatever you need in the UI-context 
    loadData(result); 
} 

// T is a type of the result, should be changed 
private async Task<T> RunProcessInBackGround() 
{ 
    var tcs = new TaskCompletionSource<T>(); 
    // run your process 
    var process new Process {/* your params here */}; 
    process.Exited += (sender, args) => 
     { 
      // here your process has already done his job 
      tcs.SetResult(result); 
      process.Dispose(); 
     }; 
    // process will start as a separate process, no need to create a thread to wait for it 
    process.Start(); 
    // return the task which will be awaited for 
    return tcs.Task; 
}