自己写的异步方法 [英] Write your own async method

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

问题描述

我想知道如何编写自己的异步方法正确的方式。

我看过很多很多帖子解释是这样的异步/计谋模式:

<一个href="http://msdn.microsoft.com/en-us/library/hh191443.aspx">http://msdn.microsoft.com/en-us/library/hh191443.aspx

  //三件事情要注意在签名:
//  - 该方法具有异步修改。
//  - 返回类型是任务或任务&LT; T&取代。 (请参见返回类型一节)。
//这里,任务&LT; INT&GT;因为return语句返回一个整数。
//  - 的方法名称结尾异步。
异步任务&LT; INT&GT; AccessTheWebAsync()
{
    //你需要添加一个引用到System.Net.Http申报客户端。
    HttpClient的客户端=新的HttpClient();

    // GetStringAsync返回任务&LT;字符串取代。这意味着,当你等待
    //任务,你会得到一个字符串(urlContents)。
    任务&LT;字符串&GT; getStringTask = client.GetStringAsync(http://msdn.microsoft.com);

    //你可以在这里做的工作,不依赖于从GetStringAsync字符串。
    DoIndependentWork();

    //该计谋运营商暂停AccessTheWebAsync。
    //  -  AccessTheWebAsync无法继续下去,直到getStringTask完成。
    //  - 同时,控制返回到AccessTheWebAsync的调用者。
    //  - 控制恢复这里的时候getStringTask完成。
    //  - 该计谋运营商然后检索从getStringTask的字符串结果。
    字符串urlContents =等待getStringTask;

    // return语句指定一个整数结果。
    //任何正在等待AccessTheWebAsync方法获取长度值。
    返回urlContents.Length;
}

私人无效DoIndependentWork()
{
    resultsTextBox.Text + =工作........ \ r \ N的;
}
 

这对于已经实现像

该功能的任何.NET方法的伟大工程
  • System.IO opertions
  • 数据库opertions
  • 在网络相关的操作(​​下载,上传...)

但是,如果我想要写我自己的方法,需要相当长的一段时间来完成那里只是没有方法,我可以使用和重载是在 DoIndependentWork 上面的例子中的方法?

在这个方法我可以这样做:

  • 字符串操作
  • 计算
  • 在处理我自己的对象
  • 集结,比较,筛选,分组处理的东西
  • 列表操作,添加,删除,应对

我又已经在很多很多帖子里的人只是做了以下的(再次以上面的例子),迷迷糊糊:

 异步任务&LT; INT&GT; AccessTheWebAsync()
{
    HttpClient的客户端=新的HttpClient();

    任务&LT;字符串&GT; getStringTask = client.GetStringAsync(http://msdn.microsoft.com);

    等待DoIndependentWork();

    字符串urlContents =等待getStringTask;

    返回urlContents.Length;
}

私人任务DoIndependentWork()
{
    返回Task.Run(()=&GT; {

        //字符串操作
        //计算
        //处理我自己的对象
        //集结,比较,筛选,分组,搬运东西
        //列表操作,添加,删除,应对
    });
}
 

您可能会注意到的变化是 DoIndependentWork 现在返回任务,并在 AccessTheWebAsync 任务的方法有一个等待

在重负载操作,现在封装在一个 Task.Run(),这是所有需要? 如果这一切都需要就是我需要做的是提供异步方法在我的图书馆每个单独的方法如下唯一:

 公共类FooMagic
{
    公共无效DoSomeMagic()
    {
        //做一些SYNCHRON魔...
    }

    公共任务DoSomeMagicAsync()
    {
        //做一些异步神奇......?!?
        返回Task.Run(()=&GT; {DoSomeMagic();});
    }
}
 

将是很好,如果你能解释给我,因为即使是高投这样的问题: 如何编写简单的异步方法?

只是说明它与现有的方法,只是使用ASYN /等待着喜欢的提到的问题,此评论的模式把它给点意见: <一href="http://stackoverflow.com/questions/6772789/how-to-write-simple-async-method#comment18867834_10537761">How编写简单的异步方法?

解决方案
  

将是很好,如果你能解释给我:如何编写简单的异步   方法是什么?

首先,我们需要了解什么是异步方法手段。当一个人暴露了一个异步方法向最终用户消耗异步方法,你就告诉他:听着,这种方法将很快恢复到你在不久的将来的某个时候完成的。这就是你要保证你的用户是什么。

现在,我们需要了解如何工作使这个承诺的可能。当你问你的问题,为什么简单地增加一个 Task.Run 我的方法中,使之有效使用计谋关键字?

A 工作实施 GetAwaiter 模式,这意味着它返回一个对象称为 awaiter (它实际上是一个名为<一个href="http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.taskawaiter%28v=vs.110%29.aspx"><$c$c>TaskAwaiter).该 TaskAwaiter 对象实现或者<一href="http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.inotifycompletion(v=vs.110).aspx"><$c$c>INotifyCompletion或<一href="http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.icriticalnotifycompletion(v=vs.110).aspx"><$c$c>ICriticalNotifyCompletion接口,露出了 OnCompleted 方法。

所有这些东西都轮流使用的编译器,一旦计谋关键字被使用。编译器将确保在设计时,你的对象实现 GetAwaiter ,并依次用它来编译code到一个状态机,这将使你的程序得到控制回一次期待已久的来电,并继续当工作完成。

现在,有一些准则来遵循。一个真正的异步方法不使用额外的线程在幕后做的工作(斯蒂芬·克利里解释了这个奇妙的的 没有线程),这意味着露出一种方法,它使用了 Task.Run 里面是有点误导消费者你的API的,因为他们将承担参与你的任务没有额外的线程。你应该做的是暴露你的API同步,并让使用用户卸载它 Task.Run 本人,控制执行流程。

异步方法主要用于 I / O密集​​型的操作,因为这些自然不需要任何线程被消耗,而IO操作执行,这就是为什么我们看到他们很多在课堂负责做IO操作,如硬盘驱动器的呼叫,网络电话等。

我建议您阅读并行PFX车队的文章我应该公开异步包装器同步方法?其中谈到正是你正在尝试做什么,它为什么不推荐使用。

I would like to know how to write your own async methods the "correct" way.

I have seen many many posts explaining the async/await pattern like this:

http://msdn.microsoft.com/en-us/library/hh191443.aspx

// Three things to note in the signature: 
//  - The method has an async modifier.  
//  - The return type is Task or Task<T>. (See "Return Types" section.)
//    Here, it is Task<int> because the return statement returns an integer. 
//  - The method name ends in "Async."
async Task<int> AccessTheWebAsync()
{ 
    // You need to add a reference to System.Net.Http to declare client.
    HttpClient client = new HttpClient();

    // GetStringAsync returns a Task<string>. That means that when you await the 
    // task you'll get a string (urlContents).
    Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

    // You can do work here that doesn't rely on the string from GetStringAsync.
    DoIndependentWork();

    // The await operator suspends AccessTheWebAsync. 
    //  - AccessTheWebAsync can't continue until getStringTask is complete. 
    //  - Meanwhile, control returns to the caller of AccessTheWebAsync. 
    //  - Control resumes here when getStringTask is complete.  
    //  - The await operator then retrieves the string result from getStringTask. 
    string urlContents = await getStringTask;

    // The return statement specifies an integer result. 
    // Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
    return urlContents.Length;
}

private void DoIndependentWork()
{
    resultsTextBox.Text += "Working........\r\n";
}

This works great for any .NET Method that already implements this functionality like

  • System.IO opertions
  • DataBase opertions
  • Network related operations (downloading, uploading...)

But what if I want to write my own method that takes quite some time to complete where there just is no Method I can use and the heavy load is in the DoIndependentWork method of the above example?

In this method I could do:

  • String manipulations
  • Calculations
  • Handling my own objects
  • Aggregating, comparing, filtering, grouping, handling stuff
  • List operations, adding, removing, coping

Again I have stumbled across many many posts where people just do the following (again taking the above example):

async Task<int> AccessTheWebAsync()
{ 
    HttpClient client = new HttpClient();

    Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

    await DoIndependentWork();

    string urlContents = await getStringTask;

    return urlContents.Length;
}

private Task DoIndependentWork()
{
    return Task.Run(() => {

        //String manipulations
        //Calculations
        //Handling my own objects
        //Aggregating, comparing, filtering, grouping, handling stuff
        //List operations, adding, removing, coping
    });
}

You may notice that the changes are that DoIndependentWork now returns a Task and in the AccessTheWebAsync task the method got an await.

The heavy load operations are now capsulated inside a Task.Run(), is this all it takes? If that's all it takes is the only thing I need to do to provide async Method for every single method in my library the following:

public class FooMagic
{
    public void DoSomeMagic()
    {
        //Do some synchron magic...
    }

    public Task DoSomeMagicAsync()
    {
        //Do some async magic... ?!?
        return Task.Run(() => { DoSomeMagic(); });
    }
}

Would be nice if you could explain it to me since even a high voted question like this: How to write simple async method?

Only explains it with already existing methods and just using asyn/await pattern like this comment of the mentioned question brings it to the point: How to write simple async method?

解决方案

Would be nice if you could explain it to me: How to write simple async method?

First, we need to understand what an async method means. When one exposes an async method to the end user consuming the async method, you're telling him: "Listen, this method will return to you quickly with a promise of completing sometime in the near future". That is what you're guaranteeing to your users.

Now, we need to understand how Task makes this "promise" possible. As you ask in your question, why simply adding a Task.Run inside my method makes it valid to be awaited using the await keyword?

A Task implements the GetAwaiter pattern, meaning it returns an object called an awaiter (Its actually called TaskAwaiter). The TaskAwaiter object implements either INotifyCompletion or ICriticalNotifyCompletion interfaces, exposing a OnCompleted method.

All these goodies are in turn used by the compiler once the await keyword is used. The compiler will make sure that at design time, your object implements GetAwaiter, and in turn use that to compile the code into a state machine, which will enable your program to yield control back to the caller once awaited, and resume when that work is completed.

Now, there are some guidelines to follow. A true async method doesn't use extra threads behind the scenes to do its job (Stephan Cleary explains this wonderfully in There Is No Thread), meaning that exposing a method which uses Task.Run inside is a bit misleading to the consumers of your api, because they will assume no extra threading involved in your task. What you should do is expose your API synchronously, and let the user offload it using Task.Run himself, controlling the flow of execution.

async methods are primarily used for I/O Bound operations, since these naturally don't need any threads to be consumed while the IO operation is executing, and that is why we see them alot in classes responsible for doing IO operations, such as hard drive calls, network calls, etc.

I suggest reading the Parallel PFX teams article Should I expose asynchronous wrappers for synchronous methods? which talks exactly about what you're trying to do and why it isn't recommended.

这篇关于自己写的异步方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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