Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何知道所有异步/等待已完成?_C#_Asynchronous_Async Await - Fatal编程技术网

C# 如何知道所有异步/等待已完成?

C# 如何知道所有异步/等待已完成?,c#,asynchronous,async-await,C#,Asynchronous,Async Await,我是异步编程新手,正在尝试编写一些测试代码,看看我能用它做些什么 下面是我的测试控制台应用程序代码,调用一个异步方法,它将把一些现有的.docx文件发布到我的web api并转换为pdf static void Main(string[] args) { //async testing - 5 files batch Console.WriteLine("Job Start:"); for (int i = 0; i < 5

我是异步编程新手,正在尝试编写一些测试代码,看看我能用它做些什么

下面是我的测试控制台应用程序代码,调用一个异步方法,它将把一些现有的.docx文件发布到我的web api并转换为pdf

    static void Main(string[] args)
    {
        //async testing - 5 files batch
        Console.WriteLine("Job Start:");

        for (int i = 0; i < 5; i++)
        {
            var filestream = File.Open(@"c:\pdftest\" + i.ToString() +@".docx", FileMode.Open);

            //delegate
            Action act = async () =>
            {
                await test(filestream, i.ToString());
                filestream.Dispose();
            };

            act();
        }

        Console.WriteLine("End.");
        Console.ReadLine();
    }
static void Main(字符串[]args)
{
//异步测试-5个文件批处理
Console.WriteLine(“作业开始:”);
对于(int i=0;i<5;i++)
{
var filestream=File.Open(@“c:\pdftest\”+i.ToString()++.docx”,FileMode.Open);
//委派
Action act=async()=>
{
等待测试(filestream,i.ToString());
Dispose();
};
act();
}
控制台。写入线(“结束”);
Console.ReadLine();
}
方法是:

    static async Task<int> test(FileStream fs, string id)
    {
        var content = new StreamContent(fs);
        var client = new HttpClient();

        var startTime = DateTime.Now;

        //post to web api
        var response = await client.PostAsync("http://localhost:50348/PDFConvert/Convert?name=" + id, content);

        var ts = DateTime.Now - startTime;

        Console.WriteLine("Time Cost: " + ts.TotalSeconds.ToString() + " seconds, " + response.Content.ReadAsStringAsync().Result.Replace("\"", ""));

        client.Dispose();
        return 0;

    }
静态异步任务测试(FileStream fs,字符串id)
{
var内容=新流量内容(fs);
var client=新的HttpClient();
var startTime=DateTime.Now;
//发布到web api
var response=wait client.PostAsync(“http://localhost:50348/PDFConvert/Convert?name=“+id,内容);
var ts=DateTime.Now-startTime;
Console.WriteLine(“时间开销:+ts.TotalSeconds.ToString()+”秒,+response.Content.ReadAsStringAsync().Result.Replace(“\”,”);
client.Dispose();
返回0;
}
到目前为止,它还可以工作,但有一个问题是“结束”。在控制台窗口的“作业开始:”之后打印,然后等待输出

所以我的问题是:
1.所有异步/等待完成后如何打印“结束”消息?
2.不确定这是否是最佳实践,因此对现有规范有何建议

非常感谢

我不熟悉异步编程

我建议先写我的文章,然后再写我的文章

不要将
async
lambda与
Action
委托类型一起使用;这会导致
async void
方法。
async void
方法的一个缺点是,您无法轻松判断它们何时完成

Async无法与控制台应用程序自然匹配。您可以在异步代码上阻止主线程,但这不是在任何类型的其他应用程序中使用的好模式:

static void Main(string[] args)
{
  Console.WriteLine("Job Start:");

  MainAsync().GetAwaiter().GetResult();

  Console.WriteLine("End.");
  Console.ReadLine();
}

static async Task MainAsync()
{
  for (int i = 0; i < 5; i++)
  {
    using (var filestream = File.Open(@"c:\pdftest\" + i.ToString() +@".docx", FileMode.Open))
      await test(filestream, i.ToString());
  }
}
我不熟悉异步编程

我建议先写我的文章,然后再写我的文章

不要将
async
lambda与
Action
委托类型一起使用;这会导致
async void
方法。
async void
方法的一个缺点是,您无法轻松判断它们何时完成

Async无法与控制台应用程序自然匹配。您可以在异步代码上阻止主线程,但这不是在任何类型的其他应用程序中使用的好模式:

static void Main(string[] args)
{
  Console.WriteLine("Job Start:");

  MainAsync().GetAwaiter().GetResult();

  Console.WriteLine("End.");
  Console.ReadLine();
}

static async Task MainAsync()
{
  for (int i = 0; i < 5; i++)
  {
    using (var filestream = File.Open(@"c:\pdftest\" + i.ToString() +@".docx", FileMode.Open))
      await test(filestream, i.ToString());
  }
}

除非您正在编写事件处理程序,并且如果您强制它成为导致
异步无效
委托的
操作
委托,否则决不应执行
异步无效

将您的代理更改为
Func
,然后您可以接受任务数组并对其执行
WaitAll

static void Main(string[] args)
{
    //async testing - 5 files batch
    Console.WriteLine("Job Start:");

    var tasks = new Task[5];

    for (int i = 0; i < 5; i++)
    {
        var filestream = File.Open(@"c:\pdftest\" + i.ToString() +@".docx", FileMode.Open);

        //Moved i.ToString() out of the delegate to fix a potential bug with variable capture.
        var stringToPrint = i.ToString()

        //delegate
        Func<Task> act = async () =>
        {
            await test(filestream, stringToPrint);
            filestream.Dispose();
        };

        var task = act();
        tasks[i] = task;
    }

    //In a non console program you will likely want to do "await Task.WhenAll(tasks);" instead.
    Task.WaitAll(tasks);

    Console.WriteLine("End.");
    Console.ReadLine();
}
static void Main(字符串[]args)
{
//异步测试-5个文件批处理
Console.WriteLine(“作业开始:”);
var任务=新任务[5];
对于(int i=0;i<5;i++)
{
var filestream=File.Open(@“c:\pdftest\”+i.ToString()++.docx”,FileMode.Open);
//将i.ToString()移出委托以修复变量捕获的潜在错误。
var stringToPrint=i.ToString()
//委派
Func act=async()=>
{
等待测试(filestream、stringToPrint);
Dispose();
};
var task=act();
任务[i]=任务;
}
//在非控制台程序中,您可能希望改为“wait Task.WhenAll(tasks);”。
Task.WaitAll(任务);
控制台。写入线(“结束”);
Console.ReadLine();
}

除非您正在编写事件处理程序,并且如果您强制它成为导致
异步无效
委托的
操作
委托,否则决不能执行
异步无效
委托

将您的代理更改为
Func
,然后您可以接受任务数组并对其执行
WaitAll

static void Main(string[] args)
{
    //async testing - 5 files batch
    Console.WriteLine("Job Start:");

    var tasks = new Task[5];

    for (int i = 0; i < 5; i++)
    {
        var filestream = File.Open(@"c:\pdftest\" + i.ToString() +@".docx", FileMode.Open);

        //Moved i.ToString() out of the delegate to fix a potential bug with variable capture.
        var stringToPrint = i.ToString()

        //delegate
        Func<Task> act = async () =>
        {
            await test(filestream, stringToPrint);
            filestream.Dispose();
        };

        var task = act();
        tasks[i] = task;
    }

    //In a non console program you will likely want to do "await Task.WhenAll(tasks);" instead.
    Task.WaitAll(tasks);

    Console.WriteLine("End.");
    Console.ReadLine();
}
static void Main(字符串[]args)
{
//异步测试-5个文件批处理
Console.WriteLine(“作业开始:”);
var任务=新任务[5];
对于(int i=0;i<5;i++)
{
var filestream=File.Open(@“c:\pdftest\”+i.ToString()++.docx”,FileMode.Open);
//将i.ToString()移出委托以修复变量捕获的潜在错误。
var stringToPrint=i.ToString()
//委派
Func act=async()=>
{
等待测试(filestream、stringToPrint);
Dispose();
};
var task=act();
任务[i]=任务;
}
//在非控制台程序中,您可能希望改为“wait Task.WhenAll(tasks);”。
Task.WaitAll(任务);
控制台。写入线(“结束”);
Console.ReadLine();
}

您可以在Linq Select方法中使用异步lambda来迭代任务列表并等待它们完成

   var list = Enumerable.Range(1,5).Select (
          async i => {
                var filestream = File.Open(@"c:\pdftest\" + i.ToString() +@".docx", FileMode.Open);
                await test(filestream, i.ToString());
                filestream.Dispose();
                }
     );
    Task.WaitAll (list.ToArray ());

如果它不是一个控制台应用程序,而是一个异步上下文,那么您可以使用
whalll
而不是
WaitAll

您可以在Linq Select方法中使用异步lambda来迭代任务列表并等待它们完成

   var list = Enumerable.Range(1,5).Select (
          async i => {
                var filestream = File.Open(@"c:\pdftest\" + i.ToString() +@".docx", FileMode.Open);
                await test(filestream, i.ToString());
                filestream.Dispose();
                }
     );
    Task.WaitAll (list.ToArray ());

如果它不是一个控制台应用程序,而是一个异步上下文,那么你可以使用
whalll
而不是
WaitAll

谢谢,它在“结束”部分工作,但会出现另一个问题:任务一个接一个地运行,而不是并行运行。我知道控制台应用程序不是一个好的测试示例,所以我将尝试用winforms编写一些东西。@blk25t:I u更新了您更新的问题的答案。谢谢,它在“结束”部分起作用,但会出现另一个问题:任务一个接一个地运行,而不是并行运行。我知道您的想法,控制台应用程序不是一个很好的示例