异步方法不会将控制权返回给调用者

时间:2014-07-25 07:04:08

标签: c# .net task-parallel-library async-await

UploadToServer完全执行之前,控制权返回到main方法。我应该从Task.Run()移除UploadToServer还是明确地执行WaitAll

public class Uploader
{
    async public Task<int> Upload(int i)
    {
        int incremented = 0;
        var t = UploadToServer(i);
        if (t != null)
        {
            incremented = await t;
        }
        return incremented;
    }

    async private Task<int> UploadToServer(int i)
    {
        int incremented = 0;
        await Task.Run(() =>
        {
            //Console.ReadLine();
            //Actual upload operation
            incremented = i + 1;
        });
        return incremented;
    }
}


class Program
{
    static void Main(string[] args)
    {
        Uploader upl = new Uploader();
        var res = upl.Upload(10).Result;
    }
}

2 个答案:

答案 0 :(得分:4)

当你await async方法时,控制权会被回馈给调用者。您所遇到的是正确的async行为。

如果您不希望在执行操作时返回该方法,请执行同步。 如果您尝试做的是I / O绑定工作(比如将内容上传到服务器),请不要使用Task.Run,因为I / O绑定会自然地暴露异步端点,从而消除了对不必要线程的需求这个过程。以HttpClient为例,它展示了一堆XXXAsync方法。

答案 1 :(得分:0)

以这种方式尝试

private Task<int> UploadToServer(int i)
{
    int incremented = 0;
    return Task.Run(() =>
    {
        //Console.ReadLine();
        //Actual upload operation
        return incremented = i + 1;
    });
}

或以这种方式

private async Task<int> UploadToServer(int i)
{
     return await Task.Run(() => DoSomething(i)).Wait();
}

private int DoSomething(int i)
{
    //Console.ReadLine();
    //Actual upload operation
     return i+1;
}

请注意,这些示例并非特别有用。 认为背景线程应该过自己的生活。

在你的情况下,我想你可以使用框架的HttpClient类的一些异步方法

实施例

private async Task<int> GetWebPageHtmlSizeAsync()
{
  var client = new HttpClient();
  var html = await client.GetAsync("http://www.test.com/");
  return html.Length;
}

<强>更新

我已经测试了这段代码并且它运行了

static void Main(string[] args)
{
     Uploader upl = new Uploader();
     var res = upl.Upload(10).Result;
}


public class Uploader 
{
    async public Task<int> Upload(int i)
    {
        int incremented = 0;
        var t = UploadToServer(i);
        if (t != null)
        {
            incremented = await t;
        }
        return incremented;
    }

    private async Task<int> UploadToServer(int i)
    {
        return await Task.Run(() => DoSomething(i));
    }

    private int DoSomething(int i)
    {
        //Console.ReadLine();
        //Actual upload operation
        Thread.Sleep(2000);
        return i + 1;
    }
}

主程序在收到正确的值和控制权之前等待2秒。

查看这篇Should I expose asynchronous wrappers for synchronous methods?文章,了解何时以及如何使用异步方法。在您的具体示例中,您无法从task.run获得优势。我只提供了一个代码的工作示例。