我想在 C# 控制臺應用程式中測驗 async 和 await,所以我撰寫了這個測驗代碼。當我在 Winforms 應用程式中使用 async/await 時,例如:在 ButtonClicked 事件處理函式中呼叫這個 doSth。它會在另一個執行緒中延遲 3000 毫秒,并在 MainThread 中輸出“doSth execute finished”。但是在這個控制臺應用程式中,它在作業執行緒中輸出“doSth execute finished”,為什么?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp12
{
class Program
{
static void Main(string[] args)
{
doSth();
Console.WriteLine("doSth call finished.");
Thread.Sleep(5000);
Console.WriteLine("Main finished.");
}
private static async void doSth()
{
Console.WriteLine("doSth execute Started...");
await Task.Delay(3000);
Console.WriteLine("doSth execute finished.");
}
}
}
這是 Winforms 應用程式中的測驗代碼
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
doSth();
Console.WriteLine("doSth call finished.");
Thread.Sleep(5000);
Console.WriteLine("Main finished.");
}
private static async void doSth()
{
Console.WriteLine("doSth execute Started...");
await Task.Delay(3000);
Console.WriteLine("doSth execute finished.");
}
}
}
這是控制臺應用程式中的堆疊跟蹤,最終輸出是:
doSth execute Started...
doSth call finished.
doSth execute finished.
Main finished.
請按任意鍵繼續. . .
這是 Winforms 應用程式中的堆疊跟蹤,輸出為:
doSth execute finished.
doSth execute Started...
doSth call finished.
Main finished.
如果我洗掉 Thread.Sleep(5000) 并使主執行緒不休眠,并且在控制臺應用程式中,它將丟失輸出并且不會呼叫 doSth 函式的第二個輸出。在 Winforms 應用程式中,沒有效果。
uj5u.com熱心網友回復:
首先,async/await 并不意味著會有其他執行緒在執行。如果 await 運算子被命中,那么那段代碼的執行就會停在那里(并等待),而在這個操作等待的同時,同一個執行緒可以接受更多的作業(更多的任務要做)。
因此,異步代碼是盡可能多地重用相同的執行緒,而不是跨越盡可能多的執行緒執行代碼。
洗掉時,Thread.Sleep您只需完成作業即可。您剛剛完成運行應用程式,而后臺的任務仍在運行。但它已因您的應用程式而終止。
uj5u.com熱心網友回復:
最終,無論何時您鍵入async void,您都可能犯了一個錯誤(對 winform 上的事件處理程式稍加注意);這里的解決方法是等待(如果您唯一的非后臺執行緒,即Main入口點,退出:然后控制臺應用程式終止):
static async Task Main(string[] args)
{
await doSthAsync();
// ...
}
private static async Task doSthAsync() {...}
請注意,異步和并發/并行是非常不同的事情;如果您的意圖是實作并發,那么也許:
static async Task Main(string[] args)
{
var pending = Task.Run(doSthAsync);
// ...
await pending; // to allow parallel work to finish
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/347997.html
上一篇:如何使用webclient下載檔案,使用memortstream將它們保存為gif型別影像,同時還報告進度?
下一篇:如何檢查檔案夾是否為空?
