如果第一个代码正在执行,如何等待?

时间:2017-02-23 12:05:09

标签: c# .net multithreading asynchronous async-await

我有一种情况,当用户点击一个tabitem时,用户创建一个类的实例。这个类包含一个绘制图形的函数,它非常耗时,因此它被写成异步。

现在问题是让用户第一次点击选项卡并且类实例化并且长进程长时间工作,同时前一个异步任务没有完成并且用户再次在同一个tabitem上单击。

在这种情况下,我必须等到上一个异步任务没有完成,然后第二次点击到tabitem必须创建实例后,异步任务被完成(它应该等到第一个异步进程没有finshed)。

代码在这里:

if (selectedTabIndex == 2) //What is the user selected second time whil the previous task is still not finshed ? 
{         
    DrawGraph obj= new DrawGraph(selectedItem.Name);
 }   

我在DrawGraph类构造函数中的某处完成了:

 public DrawGraph(string Name)
 {
   timeConsumingProcess(Name);
 }

 public async void timeConsumingProcess(string Name)
 {       
   await  startTaimeConsumingProcess();
 }

我想要的是当用户第二次单击此选项卡项目编号= 2时,它必须等到上一个异步任务到finsh然后它必须再次实例化DrawGraph类到   再次重新启动异步。

如何实现它?

2 个答案:

答案 0 :(得分:3)

  

在这种情况下,我必须等到上一次异步任务没有完成,然后在第二次点击到tabitem必须创建实例后,异步任务才能完成

然后让您的代码(a)等待上一个任务:

private Task drawGraph = null;
...
if (selectedTabIndex == 2)
{
  if (drawGraph != null)
    await drawGraph;
  DrawGraph obj = new DrawGraph(selectedItem.Name);
  drawGraph = obj.timeConsumingProcess();
}

...

private readonly string name;
public DrawGraph(string Name)
{
  name = Name;
}

public async Task timeConsumingProcess()
{
  await  startTaimeConsumingProcess();
}

请注意,这要求您使用async Task代替async void,这无论如何都是好的,因为您应该avoid async void

答案 1 :(得分:1)

您可以将表示长时间运行操作的任务存储在表单中的实例变量中,并使用它来检查任务是否仍在运行。

private Task drawGraphTask = null;

private void button1_Click(object sender, EventArgs e)
{
    DrawGraph();
}

private async void DrawGraph()
{
    // Only perform task when this is the first time 
    // or the previous task is already completed
    if (drawGraphTask == null || drawGraphTask.IsCompleted)
    {
        drawGraphTask = startTimeConsumingProcess();
        await drawGraphTask;
    }
    else
    {
        MessageBox.Show("Task already active");
    }
}

private Task startTimeConsumingProcess()
{
    // Your Code here
    return Task.Delay(5000);
}

从构造函数内部启动异步活动并不好。将异步逻辑移到DrawGraph类之外,并在表单级别实例化异步类。