如何在不阻止UI的情况下执行繁重的同步操作?

时间:2014-01-14 10:49:45

标签: c#

我有一个包含Run()方法的类,该方法执行阻止UI的繁重操作。 我已经创建了该类的几个实例,我需要同步执行Run(),而无需阻止UI。 我已经设法使用BackgroundWorker但我不喜欢这个解决方案,因为“Application.DoEvents()”并且因为如果我需要等待后台工作者完成,那么没有使用BW。我应该使用同步操作。 任何想法我可以使用什么呢?

class MyClass
{
    public void Run()
    {
        for (int i = 0; i < 1000; i++)
        {
            Console.WriteLine(i);
        }
    }
}


public partial class Form1 : Form
{
    List<MyClass> lmc = new List<MyClass>();

    public Form1()
    {
        InitializeComponent();

        MyClass m1 = new MyClass();
        MyClass m2 = new MyClass();

        lmc.Add(m1);
        lmc.Add(m2);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        foreach (MyClass item in lmc)
        {
            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += bw_DoWork;
            bw.WorkerSupportsCancellation = true;
            bw.RunWorkerAsync(item);
            while (bw.IsBusy)
            {
                Application.DoEvents();
            }
        }
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        ((MyClass)e.Argument).Run();
        ((BackgroundWorker)sender).CancelAsync();
    }
}

1 个答案:

答案 0 :(得分:1)

“DoEvents”确实不是一个好方法。 我建议使用TPL任务。

private void button1_Click(object sender, EventArgs e)
{
    Task t = new Task(() =>
    {
        lmc.ForEach(l => l.Run());
    });

    t.Start();

    t.ContinueWith(_ =>
    {
        Invoke(new System.Action(UploadDone));
    });

}

private void UploadDone()
{
    Console.Write("Done");
}

发布UI的唯一方法是发布主线程。你必须开始一个新的线程。

BTW,如果lmc任务没有相互转发,你也可以Parallel Foreach

谢谢,
阿米尔