异步/等待 wpf 应用程序中的方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19421973/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:52:44  来源:igfitidea点击:

async /await for methods in wpf aplication

c#wpfasynchronous

提问by Sasha

I have such question. For example I create dynamically custom userControl using mvvm pattern. So I've sended a command to create an userControl. So creation looks like

我有这样的疑问。例如,我使用 mvvm 模式动态创建自定义 userControl。所以我发送了一个命令来创建一个 userControl。所以创作看起来像

private async Task<bool> OnAddUserControl1(List<ALV_VM_ADWERT> control)
{
    try
    {
        _cancellationTokenSource = new CancellationTokenSource();
        var userControl = _userControlsContainer.CreateUserControl1(control);

        var task1 = Task.Factory.StartNew(() =>
        {
            userControl.ViewModel.InOperationEvent += OnUsercontrolInOperationChanged;
            userControl.ViewModel.ValueTypeChangedEvent += OnValueTypeChanged;
            userControl.ViewModel.SetExpandableName += OnSetExpandableName;
        }, _cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext());

        var task2 = Task.Factory.StartNew(() => FinalCreatingStep(userControl, control[0].RAUMNAME.Trim()), _cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext());
        await Task.WhenAll(task1, task2);
        return true;
    }
    catch (Exception)
    {
        return false;
    }                
}

and my question is - does it make sence to create child tasks, or it is better to have code without child tasks? And if the answer is yes, then should I make all methods async? If not, what methods I should not make async?

我的问题是 - 创建子任务是否有意义,还是没有子任务的代码更好?如果答案是肯定的,那么我应该将所有方法设为异步吗?如果没有,我不应该使用哪些方法进行异步?

回答by Gusdor

Do those event subscriptions really need to be asynchronous? You may be trying too hard to use asynchronous code.

这些事件订阅真的需要异步吗?您可能过于努力地使用异步代码。

The user control constructor is usually the most time consuming part and must be done on the UI thread. Asynchronous operations are generally only required when some form of IO or processing is involed;

用户控件构造函数通常是最耗时的部分,必须在 UI 线程上完成。异步操作一般只在涉及某种形式的 IO 或处理时才需要;

  • Reading Files
  • Writing Files
  • Processing large data sets
  • Crossing the process boundary to talk to a server or connect device
  • 读取文件
  • 写文件
  • 处理大型数据集
  • 跨越进程边界与服务器对话或连接设备

In short, an asynchronous task is probably overkill here.

简而言之,异步任务在这里可能有点矫枉过正。

回答by Bassam Alugili

Does it make sence to create child tasks, or it is better to have code without child tasks?

创建子任务是否有意义,还是没有子任务的代码更好?

It is depending on your requirements. If your UI will blocked (Freeze) for long time you have to create a child task, otherwise not!

这取决于您的要求。如果您的 UI 会长时间阻塞(冻结),您必须创建一个子任务,否则不会!

And if the answer is yes, then should I make all methods async? If not, what methods I should not make async?

如果答案是肯定的,那么我应该将所有方法设为异步吗?如果没有,我不应该使用哪些方法进行异步?

Here it is also depending on your requirements and your .Net Version. If you are using .NET 4.5 the easiest way to do that with Async await. If you are using .Net 3.5 than just use Task. If .Net 2 use BackgorundWorker else use Thread class. ONLY Asynchrony methods must get the word async. Other methods you do not have to change them. In other words only the method which blocked the UI.

这也取决于您的要求和您的 .Net 版本。如果您使用的是 .NET 4.5,最简单的方法是使用 Async await。如果您使用的是 .Net 3.5,请不要只使用 Task。如果 .Net 2 使用 BackgorundWorker,则使用 Thread 类。只有异步方法必须得到异步这个词。其他方法您不必更改它们。换句话说,只有阻止 UI 的方法。

回答by Stephen Cleary

Your current code doesn't make any sense.

您当前的代码没有任何意义。

The point of asynccode in a UI application is responsiveness- i.e., moving long-running operations off the UI thread. As @Gusdor pointed out, most of the use cases for asyncare I/O-based (or event-based) operations, where you don't want to block the UI thread just to wait for some result. Another use case is when you have some CPU-bound work to do, but you don't want to tie up the UI thread; in this case, you can use Task.Run.

asyncUI 应用程序中的代码点是响应性——即将长时间运行的操作移出 UI 线程。正如@Gusdor 指出的那样,大多数用例async都是基于 I/O(或基于事件)的操作,您不想阻塞 UI 线程只是为了等待某个结果。另一个用例是当您有一些 CPU 密集型工作要做,但又不想占用 UI 线程时;在这种情况下,您可以使用Task.Run.

But in your code, you're calling StartNewwith TaskScheduler.FromCurrentSynchronizationContext, which means your "child" tasks are going to execute on the UI thread. So your OnAddUserControl1is just starting tasks which will run on the same thread and asynchronously waiting for them to complete. This is a very complex way of doing nothing.

但是,在你的代码,你打电话StartNewTaskScheduler.FromCurrentSynchronizationContext的,这意味着你的“孩子”的任务是要在UI线程上执行。因此,您OnAddUserControl1只是启动将在同一线程上运行并异步等待它们完成的任务。这是一种非常复杂的无所作为的方式。

While we're on the subject of StartNew, there are a number of other problems:

在我们讨论 的主题时StartNew,还有许多其他问题:

  1. The code is passing a CancellationTokenwithout ever observing it in the delegate.
  2. The code is specifying AttachedToParentwhich is incorrect for await-compatible tasks.
  3. As mentioned above, the code is passing a TaskSchedulerwhich will run the delegate right back on the UI thread.
  1. 代码在CancellationToken没有在委托中观察它的情况下传递 a 。
  2. 代码指定AttachedToParent哪个对于await兼容任务不正确。
  3. 如上所述,代码正在传递一个TaskScheduler将在 UI 线程上运行委托的正确方法。

If you need to use background (thread pool) tasks, you should use Task.Runinstead of Task.Factory.StartNew; I go into more detail on my blog.

如果你需要使用后台(线程池)任务,你应该使用Task.Run而不是Task.Factory.StartNew; 我在我的博客上有更详细的介绍。

So for this example, it doesn't make sense to use asyncor awaitat all.

所以对于这个例子,使用async或根本没有意义await

The best way to start using asyncis to identify the I/O-bound (or event-driven) parts first (e.g., HTTP requests, database calls), make them async, and then work your way up the call stack.

开始使用的最佳方法async是首先识别 I/O 绑定(或事件驱动)部分(例如,HTTP 请求、数据库调用),创建它们async,然后按自己的方式向上调用堆栈。