2017-02-10 63 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; 
}