简体   繁体   English

从任务中回调主线程

[英]Call back to main thread from a Task

As i don' know about threads much i have a question. 由于我不了解线程,所以我有一个问题。 I wanna do something in background and in background method i wanna switch back to the main thread on certain condition otherwise work in background. 我想在背景和背景方法中做一些事情我想在某些条件下切换回主线程,否则在后台工作。 How can i achieve this functionality? 我该如何实现这一功能? I am using a call to StartSyncThread from UI class(c#) 我正在使用UI类中的StartSyncThread调用(c#)

async void StartSyncThread()
{
    await DoSyncAsync();
}

Task DoSyncAsync()
{
    return Task.Run(() => DoSync());            
}

in DoSync method i wanna switch back to main thread so that i can change UI. 在DoSync方法中,我想切换回主线程,以便我可以更改UI。 Please give me a simple solution to do this. 请给我一个简单的解决方案来做到这一点。 Thanks in advance! 提前致谢!

There are a couple of approaches. 有几种方法。

The first is to split up the synchronous method into different parts. 第一种是将同步方法分成不同的部分。 This is best if your synchronous method calculates different types of things that go into different parts of the UI: 如果您的同步方法计算进入UI不同部分的不同类型的事物,这是最好的:

async Task DoSyncAsync()
{
  myDataBoundUIProperty1 = await Task.Run(() => DoSync1());
  myDataBoundUIProperty2 = await Task.Run(() => DoSync2());
}

The second is to use progress reporting. 第二是使用进度报告。 This is best if your UI updates are all of the same type: 如果您的UI更新都是相同的类型,这是最好的:

Task DoSyncAsync()
{
  Progress<MyProgressType> progress = new Progress<MyProgressType>(progressUpdate =>
  {
    myDataBoundUIProperty = progressUpdate;
  });
  return Task.Run(() => DoSync(progress));
}
void DoSync(IProgress<MyProgressType> progress)
{
  ...
  if (progress != null)
    progress.Report(new MyProgressType(...));
  ...
}

There is a final alternative, but I strongly recommend one of the two above. 有一个最后的选择,但我强烈推荐上述两个中的一个。 The two solutions above will result in a better code design (separation of concerns). 上述两种解决方案将带来更好的代码设计(关注点分离)。 The third alternative is to pass in a TaskFactory that can be used to run arbitrary code on the UI context: 第三种方法是传入一个TaskFactory ,可以用来在UI上下文中运行任意代码:

Task DoSyncAsync()
{
  var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
  var factory = new TaskFactory(scheduler);
  return Task.Run(() => DoSync(factory));
}
void DoSync(TaskFactory factory)
{
  ...
  scheduler.StartNew(() => { ... });
  ...
}

Again, I don't advise this last solution since it conflates your UI update logic with your background task logic. 同样,我不建议这个最后的解决方案,因为它将您的UI更新逻辑与您的后台任务逻辑混淆。 But it's better than using Dispatcher or Control directly. 但它比直接使用DispatcherControl更好。

First start your async process, then call Dispatcher.BeginInvoke to get back on the UI thread. 首先启动异步过程,然后调用Dispatcher.BeginInvoke以返回UI线程。

Task.StartNew(() =>
{
   // Do Something Async

   Dispatcher.BeginInvoke(() =>
   {
      // Update Your UI Here 
   });
});

Note that Dispatcher is not a static - this relies on your code being a part of a member function for a UI object, like a method on your page object. 请注意,Dispatcher不是静态的 - 这依赖于您的代码是UI对象的成员函数的一部分,就像页面对象上的方法一样。

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

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