Interrupt和Abort最大的不同是:调用Interrupt线程会继续工作直到下次被阻塞时抛出异常,而调用Abort会立即在线程正在执行的地方抛出异常(非托管代码除外) 。
这将导致一个新的问题:.NET Framework 中的代码可能会被中止,而且不是安全的中止 。如果中止发生在FileStream被构造期间,很可能造成一个非托管文件句柄会一直保持打开直到应用程序域结束 。
协作取消模式正如上面所说Interrupt和Abort总是危险的
,替代方案就是实现一个协作模式(cooperative )
:工作线程定期检查一个用于指示是否应该结束的标识
,发起者只需要设置这个标识 , 等待工作线程响应,即可取消线程执行 。
Framework 4.0 提供了两个类CancellationTokenSource和CancellationToken来完成这个模式:
CancellationTokenSource
定义了Cancel
方法 。CancellationToken
定义了IsCancellationRequested
属性和ThrowIfCancellationRequested
方法 。
void 取消令牌(){var cancelSource = new CancellationTokenSource();cancelSource.CancelAfter(3000);var t = new Thread(() => Work(cancelSource.Token));t.Start();t.Join();}void Work(CancellationToken cancelToken){while (true){cancelToken.ThrowIfCancellationRequested();// ...Thread.Sleep(1000);}}
四、异步编程模式MSDN文档:https://learn.microsoft.com/zh-cn/dotnet/standard/asynchronous-programming-patterns/异步编程模型(APM)异步编程模型(Asynchronous Programming Model),提出于.NET Framework 1.x 的时代,基于IAsyncResult接口实现类似BeginXXX和EndXXX的方法 。
APM是建立在委托之上的,Net Core中的委托 不支持异步调用 , 也就是 BeginInvoke 和 EndInvoke 方法 。
void APM(){var uri = new Uri("https://www.albahari.com/threading/part3.aspx");Func<Uri, int> f = CalcUriStringCount;var res = f.BeginInvoke(uri, null, null);// do something_testOutputHelper.WriteLine("我可以做别的事情");_testOutputHelper.WriteLine("共下载字符数:" + f.EndInvoke(res));}int CalcUriStringCount(Uri uri){var client = new WebClient();var res = client.DownloadString(uri);return res.Length;}
EndInvoke
会做三件事:- 如果异步委托还没有结束,它会等待异步委托执行完成 。
- 它会接收返回值(也包括
ref
和out
方式的参数) 。 - 它会向调用线程抛出未处理的异常 。
不要因为异步委托调用的方法没有返回值就不调用EndInvoke,因为这将导致其内部的异常无法被调用线程察觉 。MSDN文档中明确写了 “无论您使用何种方法,都要调用 EndInvoke 来完成异步调用 。”
BeginInvoke
也可以指定一个回调委托 。这是一个在完成时会被自动调用的、接受IAsyncResult
对象的方法 。BeginInvoke
的最后一个参数是一个用户状态对象,用于设置IAsyncResult
的AsyncState
属性 。它可以是需要的任何东西,在这个例子中,我们用它向回调方法传递method
委托,这样才能够在它上面调用EndInvoke
。var uri = new Uri("https://www.albahari.com/threading/part3.aspx");Func<Uri, int> func = CalcUriStringCount;var res = func.BeginInvoke(uri, new AsyncCallback(res =>{var target = res.AsyncState as Func<string, int>;_testOutputHelper.WriteLine("共下载字符数:" + target!.EndInvoke(res));_testOutputHelper.WriteLine("异步状态:" + res.AsyncState);}), func);// do something_testOutputHelper.WriteLine("我可以做别的事情");func.EndInvoke(res);
基于事件的异步模式(EAP)基于事件的异步模式(event-based asynchronous pattern),EAP 是在 .NET Framework 2.0 中提出的,让类可以提供多线程的能力,而不需要使用者显式启动和管理线程 。这种模式具有以下能力:- 协作取消模型(cooperative cancellation model)
- 线程亲和性(thread affinity)
- 将异常转发到完成事件(forwarding exceptions)
// 这些成员来自于 WebClient 类:public byte[] DownloadData (Uri address);// 同步版本public void DownloadDataAsync (Uri address);public void DownloadDataAsync (Uri address, object userToken);public event DownloadDataCompletedEventHandler DownloadDataCompleted;public void CancelAsync (object userState);// 取消一个操作public bool IsBusy { get; }// 指示是否仍在运行
当调用基于EAP模式的类的XXXAsync方法时,就开始了一个异步操作,EAP模式是基于APM模式之上的 。
推荐阅读
- 云原生之旅 - 11)基于 Kubernetes 动态伸缩 Jenkins Build Agents
- go GMP
- iphone13出来12会降价吗_iphone13出来12能便宜多少
- 苹果13mini屏幕多大尺寸_苹果13mini屏幕尺寸
- 618红米k40pro会降价吗_618红米k40pro能便宜多少
- 我的世界漏斗与漏斗之间怎么相连(我的世界漏斗上怎么放东西)
- 洛谷 P4135 作诗 题解
- 明日方舟泳装皮肤多少源石头
- 电脑垫多高颈椎最舒服_显示器抬高多少厘米合适
- iqoo7支持无线充电吗_iqoo7电池容量是多少