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("主线程处理其他业务中..."); }