我正在学习async
和await
的基础知识,有时不清楚是否应该将方法构建为async
。
为了把问题弄清楚,我在下面写了两种方法来做同样的事情。在下面的两个示例中,mymethod()
由Button1的click事件调用,并执行(推测)相同的操作:
第一道:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private int MyMethod()
{
int x = 0;
do
{
Thread.Sleep(100);
x++;
} while (x < 10);
return x;
}
private async void button1_Click(object sender, EventArgs e)
{
Task<int> task = new Task<int>(MyMethod);
task.Start();
int MyNumber = await task;
label1.Text = MyNumber.ToString();
}
}
第二道:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async Task<int> MyMethodAsync()
{
int x = 0;
do
{
await Task.Delay(100);
x++;
} while (x < 10);
return x;
}
private async void button1_Click(object sender, EventArgs e)
{
int MyNumber = await MyMethod();
label1.Text = MyNumber.ToString();
}
}
我的困惑是,我该如何在这两种方法中选择?有没有推荐的方式?
作为一个初学者,我的倾向是只有在mymethod()
中需要异步任务时,才将mymethod()
转换为task
。但是我无法得出结论,在其他情况下,将mymethod()
作为任务来实现是否很好。
如果第一种方法适用于我们,那么第二种方法(将MyMethod转换为任务)是多余的吗,或者它甚至会产生不良后果?
这取决于你在做什么。
如果您主要是做与IO相关的工作,打开文件,等待网络等,那么第二个例子将是最合适的。这将在主线程上运行任何处理,因此您可以避免线程的开销,而线程的开销大多会被阻塞。
如果您正在进行处理密集型工作,那么第一个示例会更合适。在这种情况下,您不会有任何等待,但您可能仍然希望在后台线程上运行它,以避免阻塞UI。
区别在于第一个示例在后台线程上同步(并阻塞)执行myMethod()
,而第二个示例在dispatcher线程上直接执行异步方法,而不阻塞它。
哪一个更好取决于方法的实际操作。通常,对于CPU密集型的工作,您更喜欢后台线程,对于IO相关的工作,例如处理文件或通过网络发送或接收字节时,您更喜欢异步方法。
另请注意,您应该使用task.run
启动新任务,而不是使用task
构造函数:
Task.Run(MyMethod);