随笔,聊一聊任务取消

1,在写根plc通讯的时候,有时候需要取消任务.


一般就是需要建立 一个canceltokensource对象.

  然后将其 token参数传递给 异步的过程.(注意,过程函数必须要实现token的IscancelRequest的功能)

2,有以下几个地方

  • m_cts.Cancel():用来调用Cancel(),并且将IsCancellationRequested=true;
  • m_cts.CancleAfter();这个函数用来延迟一定时间后调用取消指令.
  • m_cts.register,事件,用来回调当事件取消后触发的事件.

有以下几个方法实现取消等待:

Task t1 = plc.OpenAsync();

               //---
               Task t2 = Task.Run(() =>//一种将没有取消功能的异步函数增加取消功能.
                {

                   do
                    {


                        if (token.IsCancellationRequested)
                        {
                            throw new Exception("通讯超时");

                        }
                        if (t1.IsFaulted) throw t1.Exception;

                   } while (!t1.IsCompleted);

               }, token
            );
                //---
               await t2;//关键功能!

可以把if那段改成 token.throwifcancellexception:就是如果cancel了,就抛出错误.可能更号店.

利用循环,在循环那里,进行捕捉任务1的异常.

方法2:使用非任务的方式,比较简单粗暴.

               Task t1= plc.OpenAsync();
                while (!t1.IsCompleted) {  token.ThrowIfCancellationRequested(); }

3,使用 t.wait(token)可以人为取消等待.


4,当在其他线程访问控件时候.https://www.cnblogs.com/songxingzhu/p/3677307.html


void  m_comm_MessageEvent( string  msg)
    {
     if (txtMessage.InvokeRequired)
     {
     InvokeCallbackmsgCallback  =   new  InvokeCallback(m_comm_MessageEvent);
     txtMessage.Invoke(msgCallback,  new   object []  { msg } );
    }
     else
     {
     txtMessage.Text  =  msg;
    }
   }


意思是当异步线程调用的时候,需要使用invoke函数,来进行封装调用.(解决了异步执行调用的问题.).

一个定时取消任务的方式:

private System.Threading.Timer t;

private void cancelJob(object obj)
{
    Thread tempT = (Thread)obj;
    if(tempT.IsAlive)
    {
        if (listBox1.InvokeRequired)
        {
            listBox1.Invoke(new Action(() => listBox1.Items.Add("作业将被取消...")));
        }
        t.Dispose();

        //做好强行中断线程前的准备工作,如回滚业务逻辑等
        tempT.Abort();

    }
}

private void bigJob()
{
    if(listBox1.InvokeRequired)
    {
        listBox1.Invoke(new Action(() => listBox1.Items.Add("开始处理大型作业...")));
    }

    Thread.Sleep(5000); //模拟耗时操作
}

private void button1_Click(object sender, EventArgs e)
{
    Thread asyncJob = new Thread(bigJob);
    asyncJob.Start();

    TimerCallback tCallBack = new TimerCallback(cancelJob);
    t = new System.Threading.Timer(tCallBack, asyncJob, 3000, 0); //3秒后启动回调函数tCallBack

    listBox1.Items.Add("主线程处理其他业务中...");

}


















原文地址:https://www.cnblogs.com/frogkiller/p/12384510.html