简体   繁体   English

如何在不阻止UI的情况下等待线程完成

[英]How to wait for thread to complete without blocking UI

I want my program to wait after below line 我希望我的程序在下面的行之后等待

frmProgressBarObj = PullMSI.ExtractByMSIName("products.txt", false);

as above method is internally calling thread through StartProcessWithProgress() method . 如上所述方法是通过StartProcessWithProgress()方法在内部调用线程。 I want that thread to be completed before //code logic -2 line gets executed. 我希望在执行代码逻辑-2行之前完成该线程。 At the same time, It should not stop UI update done by frmProgressBar.UpdateProgress(). 同时,它不应该停止由frmProgressBar.UpdateProgress()完成的UI更新。 How do I do this? 我该怎么做呢?

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;
        }
    }
}

I'm very surprised you haven't worked with any of these before but I would really recommend reading about threading in C# since it's fundamentally important to understand the intricacies and learning the language. 我很惊讶你以前没有使用过任何这些,但我真的建议你阅读C#中的线程,因为理解复杂性和学习语言对于它来说是非常重要的。

Below are three different ways you can achieve what you want: 以下是您可以实现目标的三种不同方式:

1. Using reset events (further reading: https://msdn.microsoft.com/en-us/library/system.threading.manualreseteventslim(v=vs.110).aspx ). 1.使用重置事件 (进一步阅读: https//msdn.microsoft.com/en-us/library/system.threading.manualreseteventslim ( v=vs.110 ) .aspx )。 If your C# version doesn't have the ManualResetEventSlim , replace it with ManualResetEvent and change Wait() with WaitOne() 如果您的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) Using Task Parallel Library (TPL). 2)使用任务并行库(TPL)。 Further reading: https://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx 进一步阅读: 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) Using Async/Await. 3)使用Async / Await。 Further reading: https://msdn.microsoft.com/en-us/library/hh191443.aspx 进一步阅读: 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.");
    }
}

Also good to know: 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 ), Lock ( 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 ) and Interlocked ( https://msdn.microsoft.com/en-us/library/system.threading.interlocked(v=vs.110).aspx ). 另外要了解: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 )。

If you're using .NET 4.0 (with VS2012) or above, you can do this quite easily with the Task Parallel Library and async-await : 如果您使用的是.NET 4.0(使用VS2012)或更高版本,则可以使用Task Parallel Libraryasync-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());
}

For .NET 4, you'll need to add Microsoft.Bcl.Async . 对于.NET 4,您需要添加Microsoft.Bcl.Async

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM