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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.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#_.net_Multithreading_Asynchronous_Async Await - Fatal编程技术网

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

C# 如果第一个代码正在执行,如何等待?,c#,.net,multithreading,asynchronous,async-await,C#,.net,Multithreading,Asynchronous,Async Await,我遇到过这样一种情况:当用户单击tabitem时,用户创建了一个类的实例。这个类包含一个绘制图形的函数,它非常耗时,所以是异步编写的 现在的问题是,假设用户第一次单击tab,类实例化,长流程长时间工作,同时之前的异步任务没有找到,用户再次单击同一个tabitem 在这种情况下,我必须等到上一个异步任务未完成,然后在第二次单击tabitem时,必须在第一个异步任务完成后创建实例(应该等到第一个异步进程未完成) 代码如下: if (selectedTabIndex == 2) //What is t

我遇到过这样一种情况:当用户单击tabitem时,用户创建了一个类的实例。这个类包含一个绘制图形的函数,它非常耗时,所以是异步编写的

现在的问题是,假设用户第一次单击tab,类实例化,长流程长时间工作,同时之前的异步任务没有找到,用户再次单击同一个tabitem

在这种情况下,我必须等到上一个异步任务未完成,然后在第二次单击tabitem时,必须在第一个异步任务完成后创建实例(应该等到第一个异步进程未完成)

代码如下:

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类 重新启动异步


如何实现它?

一个简单的改变就能实现这一点

public async Task DrawGraph(string Name)
{
    await timeConsumingProcess(Name);
}

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

我让
DrawGraph()
返回一个
任务
,以防您需要等待它。

如果这是一个非常耗时的过程,您可以选择在不同的线程中执行

public DrawGraph(string Name)
{
    var task = new Task(() => timeConsumingProcess(Name));
    task.Start();
}
这样你的主线程就不会被阻塞。如果要在长时间运行的任务完成后运行某些代码,请使用ContinueWith方法

public DrawGraph(string Name)
{
    _canPressTab = false;
    var task = new Task(() => timeConsumingProcess(Name));
    task.Start();
    task.ContinueWith(t => {
        _canPressTab = true;
        ...
    });
}
更新如下

如图所示,单击选项卡时可以调用Draw方法。这将检查任务是否已在运行。如果没有,则启动任务。如果任务正在运行,它将等待任务完成,然后启动新任务

    public Task task = new Task(DoSomething);
    private static void DoSomething()
    {
        Thread.Sleep(10000);
    }


    private void Draw()
    {
        //if tab is clicked run the Draw method
        if (task.Status.Equals(TaskStatus.Running))
        {
            task.Wait();
            task = new Task(DoSomething);
            task.Start();
        }
        else if (task.Status.Equals(TaskStatus.RanToCompletion))
        {
            task = new Task(DoSomething);
            task.Start();
        }
        else
        {
            task.Start();
        }
    }

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

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类之外,并使该类在表单级别的实例化成为异步的

在这种情况下,我必须等到上一个异步任务尚未完成,然后在第二次单击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
,这很好,因为您应该禁用该选项卡。

为什么不禁用该选项卡?@HristoYankov是的,我有这个想法,但我的上级不接受。使用wait不会阻止处理用户操作,因此问题仍然存在。@NineBerry您说得对。但这不是用户所要求的。用户要求任务等待,即使按钮已按下。因此,对
DrawGraph()
的下一个调用将等待上一个调用完成。我要做的是在previosu任务处理时,在if(selectedTabIndex==2)条件下等待。如果正在处理,则让它查找,然后处理下一个实例。如何执行?条件drawGraphTask==null甚至会在第二次单击时执行,因为第二次单击后调试时的参数是“Id=744,Status=RanToCompletion,Method=“{null}”,但它仍然执行该条件否,该条件检查整个任务是否为null,任务的Method属性具有什么值并不重要。