[英]How to wait for thread to complete without blocking UI
我希望我的程序在下面的行之后等待
frmProgressBarObj = PullMSI.ExtractByMSIName("products.txt", false);
如上所述方法是通过StartProcessWithProgress()方法在内部调用线程。 我希望在执行代码逻辑-2行之前完成该线程。 同时,它不应该停止由frmProgressBar.UpdateProgress()完成的UI更新。 我该怎么做呢?
namespace NS1
{
public partial class frmMain : Form
{
private void button1_Click(object sender, EventArgs e)
{
frmProgressBar frmProgressBarObj = PullMSI.ExtractByMSIName("products.txt", false);
//code logic - 2
MessageBox.Show("This is executing immediately.
I want to wait until above thread is complete");
}
}
public partial class frmProgressBar : Form
{
public void UpdateProgress(String strTextToDisplayOnProgress)
{
progressBar1.BeginInvoke(
new Action(() =>
{
progressBar1.Value++;
lblFileName.Text = strTextToDisplayOnProgress;
if (progressBar1.Value == progressBar1.Maximum)
{
this.Hide();
}
}));
}
public delegate void DelProgress();
public void StartProcessWithProgress(DelProgress delMethodCode, int maxCount)
{
InitializeProgress(maxCount);
Thread backgroundThread = new Thread(new ThreadStart(delMethodCode));
backgroundThread.Start();
}
}
public static class PullMSI
{
public static frmProgressBar ExtractByMSIName(String strProductFilePath, bool reNameMSI)
{
frmProgressBar frmProgressBar = new frmProgressBar();
frmProgressBar.StartProcessWithProgress(() =>
{
//StreamRader sr declaration and other code
while (!sr.EndOfStream)
{
//logic here
frmProgressBar.UpdateProgress("Copying sr.msiname");
}
}, 2);
return frmProgressBar;
}
}
}
我很惊讶你以前没有使用过任何这些,但我真的建议你阅读C#中的线程,因为理解复杂性和学习语言对于它来说是非常重要的。
以下是您可以实现目标的三种不同方式:
1.使用重置事件 (进一步阅读: https : //msdn.microsoft.com/en-us/library/system.threading.manualreseteventslim ( v=vs.110 ) .aspx )。 如果您的C#版本没有ManualResetEventSlim
,请将其替换为ManualResetEvent
并使用WaitOne()
更改Wait()
WaitOne()
class LockingWithResetEvents
{
private readonly ManualResetEvent _resetEvent = new ManualResetEvent(false);
public void Test()
{
MethodUsingResetEvents();
}
private void MethodUsingResetEvents()
{
ThreadPool.QueueUserWorkItem(_ => DoSomethingLong());
ThreadPool.QueueUserWorkItem(_ => ShowMessageBox());
}
private void DoSomethingLong()
{
Console.WriteLine("Doing somthing.");
Thread.Sleep(1000);
_resetEvent.Set();
}
private void ShowMessageBox()
{
_resetEvent.WaitOne();
Console.WriteLine("Hello world.");
}
}
2)使用任务并行库(TPL)。 进一步阅读: https : //msdn.microsoft.com/en-us/library/dd460717(v = vs.110).aspx
class LockingWithTPL
{
public void Test()
{
Task.Factory.StartNew(DoSomethingLong).ContinueWith(result => ShowMessageBox());
}
private void DoSomethingLong()
{
Console.WriteLine("Doing somthing.");
Thread.Sleep(1000);
}
private void ShowMessageBox()
{
Console.WriteLine("Hello world.");
}
}
3)使用Async / Await。 进一步阅读: https : //msdn.microsoft.com/en-us/library/hh191443.aspx
class LockingWithAwait
{
public void Test()
{
DoSomething();
}
private async void DoSomething()
{
await Task.Run(() => DoSomethingLong());
ShowMessageBox();
}
private async void DoSomethingLong()
{
Console.WriteLine("Doing somthing.");
Thread.Sleep(10000);
}
private void ShowMessageBox()
{
Console.WriteLine("Hello world.");
}
}
另外要了解:Mutex( https://msdn.microsoft.com/en-us/library/system.threading.mutex ( v= vs.110).aspx),Semaphore( https://msdn.microsoft.com /en-us/library/system.threading.semaphore(v=vs.110).aspx ),锁( https://msdn.microsoft.com/en-us/library/c5kehkcz.aspx ),SemaphoreSlim( HTTPS: //msdn.microsoft.com/en-us/library/system.threading.semaphoreslim(v=vs.110).aspx),Monitor(https://msdn.microsoft.com/en-us/library/system 。 threading.monitor(v = vs.110).aspx )和Interlocked( https://msdn.microsoft.com/en-us/library/system.threading.interlocked (v=vs.110).aspx )。
如果您使用的是.NET 4.0(使用VS2012)或更高版本,则可以使用Task Parallel Library
和async-await
轻松完成此操作:
private async void button1_Click(object sender, EventArgs e)
{
frmProgressBar frmProgressBarObj = await Task.Run(() =>
PullMSI.ExtractByMSIName("products.txt", false));
MessageBox.Show(string.Format("Returned {0}", frmProgressBarObj.ToString());
}
对于.NET 4,您需要添加Microsoft.Bcl.Async
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.