C#---异步多线程不能对已完成的Task执行Start

C#—不能对已完成的任务执行Start

在一次项目中出现了一个报错,不能在已完成,已出错,未完成的任务Start,不知道什么原由,会出现这样的问题,但是今天又把它复现了一遍。

1、出错代码

int sum = 0;
int Init = 0;

public Task<int> ComputerTask;

public async void InitComputerTask()
{
   
    ComputerTask = Task.Factory.StartNew(() =>
    {
        for (int i = Init; i < 100000; i++)
        {
            Thread.Sleep(800);

            sum += i;
            Log = $"sum={sum}";

            if (Source.IsCancellationRequested)
            {
                Log = "计算任务还没有执行结束,计算终止";
                break;
            }
        }
        return sum;
    }, Source.Token);

    await Task.Delay(2000);
    int Result= await ComputerTask;
    Log= $"此次计算的结果为{Result}";
}

public void StopComputerTask()
{
    if (!Source.IsCancellationRequested)
    {
        Source.Cancel();
    }
}

public void RestartComputerTask()
{
  if(  ComputerTask!=null)
    {
        Init += 1;
        ComputerTask.Start();
    }
}

代码说明:这里我定义了一个任务ComputerTask,,初始化任务是计算从0-100000 的和。StopComputerTask方法,用CancellationTakenSoure+ CancellationTaken的方法,中途可以取消任务。RestartComputerTask 重新执行此任务。

运行程序,开始任务,结束任务没问题,重启任务结果报错:
报错不能对已完成的任务Start
我不知道为啥,不能对已完成的任务进行Start。
但是这里有一个解决方法,虽然任务Start之后不能Start
如果是这样的话,那岂不是我写的任务,只能执行一次,如果我想重新启动任务就启动不了了。

2、解决问题的办法

	要想实现这个功能有一个解决办法,就是任务可以用委托来定义,用委托来定义指向任务的指针。若想重启任务,直接调用委托。这样任务就能再次被执行了。
 //单个任务
 public Func<Task> CurrtentTask;

 public async Task InitTask()
 {
     int n = 0;
     CurrtentTask = async () =>

      await Task.Run(() =>
    {
        while (!Source.IsCancellationRequested)
        {
            Thread.Sleep(1000);

            Log = "log" + (n++).ToString();
        }

        Source = new CancellationTokenSource();

    }, Source.Token);
 }

 public void CancelTask()
 {
     if (!Source.IsCancellationRequested)
     {
         Source.Cancel();
     }
 }

 public async Task ExecuteTask()
 {
     if (CurrtentTask == null)
         await InitTask();
     await CurrtentTask();
 }

 public async Task RestartTask()
 {
     if (CurrtentTask != null)
     {
         await CurrtentTask();
     }
 }

这里为了多练习,我这里又重新写了一个委托,这个委托是Func CurrentTask. 初始化这个委托变量,这个委托变量里面有异步任务,这里应用委托来包装异步任务,可以让异步任务 多次启动。为什么这里用Func 主要是因为 使用异步async void 不能破获到异常,所以这里用到async Task .通过这种方式可以让委托多次执行异步任务。而不会报错。

启动
结果:按下启动按钮,异步任务执行,按下取消按钮异步任务结束、按下重启按钮异步任务又开始执行。

3、总结归纳

在实际项目开发中,如果想要多次执行异步任务,不能直接定义次异步任务,因为一旦创建并执行此异步任务,再想要重新启动,不能用Start方法,这样会报错。
采取的解决问题的方式是,使用委托包装异步任务,这样可以多次重复执行异步任务,不会报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值