使用任务和async / await或ContinueWith时阻止冻结UI线程是不是正确?

时间:2017-07-02 11:09:28

标签: c# multithreading taskfactory

我有一个名为Do()的方法,它做了一些计算,然后将结果保存在2个不同的文件中,然后进行其他一些计算。由于文件可能很大,我想通过使用任务或类似的东西来更新文件,以防止UI冻结。我尝试使用TaskFactoryWait以及WaitAll,但他们冻结了用户界面。其他选项是ContinueWith但是之后有很多代码我无法移动它们,我认为在ContinueWith中移动所有这些代码都不是正确的事情。使用async/await可以很容易,但我必须使用.NetFramework4,所以我不能使用它们。我考虑的其他选项是调用方法并创建backgroundworker,在其中更新文件,并在Runworkercompleted event中调用方法来保留。但它甚至更加丑陋。是否有更好的方法在方法中间的单独线程/任务中执行某些操作而不影响其他代码和UI线程?这就像在单独的线程/任务中执行所有方法一样,并且在完全完成而不冻结UI之前不要离开它。

注意:我必须使用.NetFrameWork4。

方法Do是:

public void Do()
{
    //---------------
    //other codes
    //---------------

    SaveResult1();
    SaveResult2();

    //---------------
    //other codes that I can not move them up
    //---------------
}

2 个答案:

答案 0 :(得分:0)

你可以这样做:

void Do()
{
    // Some code

    Task.Factory.StartNew(() =>
    {
        SaveResult1();
        SaveResult2();
    })
    .ContinueWith(t =>
    {
        // Other code
    });
}

答案 1 :(得分:0)

要执行长时间的操作,您可以考虑一些选项。我一直喜欢的其中一个选项是beginInvoke方法。您需要做的就是制作一个与您所需方法具有相同签名的适当委托。发起授权有两种不同的方法。同步或异步。使用此方法,它允许您的UI执行它自己的工作,而第二个线程负责执行缓慢的部分。当你调用beginInvoke方法时,第一个线程产生第二个线程并继续。它还可以让您知道作业是否完成。这里方法的第一个参数是callback方法。好消息是您可以使用第二个参数将当前状态传递给回调方法。

请查看以下代码:

首先定义你的代表团

public delegate void SimpleDelegate();

然后封装你的方法并解雇它

var obj = new ClassA();
var del = new SimpleDelegate(obj.Do);
Console.WriteLine("Start");
del.BeginInvoke(null, null);
Console.WriteLine("End");
Console.ReadKey();

这是一个长时间的行动。

  public void Do()
  {
   Thread.Sleep(5000);
   Console.WriteLine("Done!");
  }