使用异步首创置业与异步功能 [英] Using async BCL with async function

查看:105
本文介绍了使用异步首创置业与异步功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经标记这是.NET 4,因为我现在用的的异步BCL

I've flagged this as .NET 4, as I am using the async BCL.

我有以下的code:

using System.Threading.Tasks;

public static async Task<ObservableCollection<MyResult>> GetMyData(Params p)
{
    DoStuffClass stuff = new DoStuffClass();
    ObservableCollection<MyResults> results = null;

    await Task.Factory.StartNew(() =>
    {
        results = stuff.LongDrawnOutProcess(p);
    });

    return results;
}

我从那个看起来是这样的一个previous版本重构:

Which I have refactored from a previous version that looked something like this:

static void GetMyDataAsync(Params p, EventHandler<MyArgs> callback)
{
    DoStuffClass stuff = new DoStuffClass();
    stuff.LoadCompleted += callback;
    stuff.LongDrawOutProcessAsync(p)
}

的灵感来自于来自这里

到目前为止,第一种情况的使用是最简单的,这就是为什么我重构;我的问题是:是否有任何陷阱,以这种方法吗?该 LongDrawnOutProcess 并击中了数据库。

By far, the usage of the first case is the easiest, which was why I refactored; my question is: are there any pitfalls to this method? The LongDrawnOutProcess does hit the database.

推荐答案

而不是依靠任务的副作用设置另一个变量,你应该使用任务的结果访问工作的结果。而在这种情况下,你是不是访问太早的结果,这是一个容易犯的错误时,使用这种编程风格之作。您还需要担心相应的内存屏障是否到位,从而改变变量将被适当地观察到。

Rather than relying on the side effect of the task setting another variable, you should use the task's Result to access the results of a Task. While in this case you aren't accessing the results too early, it is an easy mistake to make when using this style of programming. You also need to worry about whether the appropriate memory barriers are in place such that the changed variable will be properly observed.

更preferable的方法是这样的:

The more preferable method would be this:

public static async Task<ObservableCollection<MyResult>> GetMyData(Params p)
{
    DoStuffClass stuff = new DoStuffClass();

    return await Task.Factory.StartNew(() => stuff.LongDrawnOutProcess(p));
}

接下来,因为你永远不会做之后的任何等待除了返回一个值,有没有真正的理由使用异步在这里所有;你可以这样写:

Next, since you're never do anything after any await besides returning a value, there's no real reason to use async here at all; you can just write:

public static Task<ObservableCollection<MyResult>> GetMyData(Params p)
{
    DoStuffClass stuff = new DoStuffClass();

    return Task.Factory.StartNew(() => stuff.LongDrawnOutProcess(p));
}

最后,这确实有一个更根本的问题。你不使用实际的异步方法。你创建一个线程池线程,这只是会花所有的时间都坐在那里等着这个方法来完成。这是一种浪费,而异步编程的设计是为了避免这样的同步等待,而不是仅仅把他们关到另一个线程。如果你希望你的程序是台异步你还是应该使用异步方法,但你仍然可以把它转换成异步的基于任务的风格的好处:

Finally, this does have a more fundamental problem. You're not using the actual asynchronous method. You're creating a thread pool thread that is just going to spend all of its time sitting around waiting for this method to complete. That is wasteful, and the design of asynchronous programming is to avoid such synchronous waits, not to just push them off to another thread. IF you want your program to be asychronous you should still use the Async method, but you can still have the benefit of converting it to a Task based style of asynchrony:

static Task<ObservableCollection<MyResult>> GetMyDataAsync(Params p)
{
    var tcs = new TaskCompletionSource<ObservableCollection<MyResult>>();
    DoStuffClass stuff = new DoStuffClass();
    stuff.LoadCompleted += (args) => tcs.TrySetResult(args.Result);
    stuff.LongDrawOutProcessAsync(p);
    return tcs.Task;
}

这篇关于使用异步首创置业与异步功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆