Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 防止在使用任务和异步/等待或连续时冻结UI线程,是否有误?_C#_Multithreading_Taskfactory - Fatal编程技术网

C# 防止在使用任务和异步/等待或连续时冻结UI线程,是否有误?

C# 防止在使用任务和异步/等待或连续时冻结UI线程,是否有误?,c#,multithreading,taskfactory,C#,Multithreading,Taskfactory,我有一个名为Do()的方法,它进行一些计算,然后将结果保存在两个不同的文件中,然后进行一些其他计算。由于文件可能很大,我想通过使用任务或类似的东西来更新文件,以防止UI冻结。我尝试使用TaskFactory和Wait和WaitAll但它们冻结了用户界面。另一个选项是ContinueWith,但后面有很多代码,我无法将它们向上移动,我不认为将它们全部移动到ContinueWith是正确的做法。使用async/await很容易,但我必须使用.NetFramework4,所以我不能使用它们。我考虑的另

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

注意:我必须使用.NetFrameWork4

方法
Do
是:

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

    SaveResult1();
    SaveResult2();

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

您可以这样做:

void Do()
{
    // Some code

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

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

查看下面的代码:

首先定义你的授权

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!");
  }

请注意,可以在.NET4.0中使用async/await:@kevingosse谢谢。我不知道。我来测试一下。你试过使用BackgroundWorker类吗?它易于实现且快速。网上有很多很好的教程。谢谢你的回复。但正如我所提到的,在这之后是许多代码,将它们移动到
ContinueWith
部分似乎不是一个好主意。再次感谢。@Learner-为什么不呢?将其全部移动到
ContinueWith