首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

c#异步编程-Task(一)

如果操作抛出异常,铺货和传播该异常都很麻烦 无法告诉线程在结束时开始另外的工作,你必须进行join操作(在进程中阻塞当前的线程) 很难使用较小的并发(concurrent)来组件大型的并发 Task类可以很好的解决上述问题...) Task.Run(()=>{ Console.WriteLine("do it"); }); Task默认使用线程池,也就是后台线程:当主线程结束时,你创建所有的tasks都会结束。...Faulted = 7 } if (task.Status == TaskStatus.RanToCompletion) { //当当前线程状态表示完成时则执行后续操作 Console.WriteLine...4.Coninuation 一个Continuation会对Task说:“当你结束的时候,继续在做点其他的事情” Continuation通常是通过回调的方式实现的 当操作一结束,就开始执行 代码如下:...5.TaskCompletionSource TaskCompletionSource也可以用来创建Task TaskCompletionSource让你在稍后开始和结束的任意操作中创建Task 它会为你提供一个可手动执行

58410
您找到你想要的搜索结果了吗?
是的
没有找到

c#异步编程-Task(二)

二、详细内容 1.同步异步 同步操作会在返回调用者之前完成它的工作 异步操作会在返回调用者之后去做它的工作 异步的方法更为少见,会启用并发,因为他的工作会与调用者并行执行 目前见到的大部分的异步方法都是通用目的的...如果调用图中任何一个操作时长时间运行的,那么整个call graph必须运行在worker线程上,以保证UI响应。...并发的粒度适中:-一连串小的并发操作操作之间会弹回到UI线程 经验之谈 为了获得上述好处,下列操作建议异步编写: IO-bound和compute-bound操作 执行超过50毫秒的操作 另一方面过细的粒度会损害性能...异步方法如何执行 遇到await表达式,执行(正常情况下)会返回调用者 为保证task结束时,实现会跳回原方法,从停止的地方继续执行。 就像iterator里面的yield return。...直接将异常抛出回调用者的原因是为了确保可预测性和一致性。

2.5K30

使用 Task.Wait()?立刻死锁(deadlock)

当 Task 的任务结束时,会从 AsyncMethodStateMachine 中调用 Awaiter 的 OnComplete() 方法,而 await 后续方法的执行靠的就是 OnComplete...Task DoAsync() { await Task.Run(() => { }); } 无论是 WPF 还是 UWP,只要在 UI 线程上调用上述代码,必然死锁!...不在后台线程执行怎么做到的异步等待!!! 是的,读写文件,访问网络,这些 IO 阻塞的操作执行时,里面根本就没有线程,详情请阅读:There Is No Thread。...总结不会造成死锁的充分条件: 异步操作执行完后不需要回到原有线程(例如非 UI 线程和控制台线程); 异步操作不需要单独的线程执行任务。 如何避免死锁?...如有任何疑问,请 与我联系 (walter.lv@qq.com) 。

1.2K10

在.NET中执行AsyncAwait的两种错误方法

在.NET中执行异步/等待的两种错误方法 在应用开发中,我们为了提高应用程序的吞吐能力或者异步操作来减少耗时,通常会使用多线程来达到目的,而在C#语言中由于async/await必杀技的存在,大多会使用此来简化多线程操作...,async/await的具体使用方式想必大家已烂熟于心,不再赘述,今天主要谈谈在我们经常所谓的async/await操作真的是正确的吗?...() 在工作中大多使用Task.Run的代码给人的印象是异步有助于提高性能。...总结一下,以上代码非常糟糕,因为实现异步的好处是通过在线程执行任何操作(例如,等待服务响应)时“释放”线程来提高吞吐量。...上面的示例确实释放了一个线程,它也立即消耗了另一个线程来执行任务包装的代码,并且该消耗的线程在等待服务响应时被阻塞。因此,我们没有提高吞吐量,只是将工作从一个线程转移到了另一个线程。

1.3K10

使用异步操作时的注意要点(翻译)

异步操作时需要注意的要点 1.使用异步方法返回值应当避免使用void 在使用异步方法中最好不要使用void当做返回值,无返回值也应使用Task作为返回值,因为使用void作为返回值具有以下缺点 无法得知异步函数的状态机在什么时候执行完毕...()方法执行长时间堵塞线程的工作 长时间运行的工作是指在应用程序生命周期执行后台工作的线程,如:执行processing queue items,执行sleeping,执行waiting或者处理某些数据...,此类线程建议使用Task.Run方法执行,因为Task.Run方法是将任务在线程池内进行排队执行,如果线程池线程进行长时间堵塞,会导致线程池增长,进而浪费性能,所以如果想要运行长时间的工作建议直接创建一个新线程进行工作...{ var thread = new Thread(ProcessQueue) { // 设置线程为背后线程,使得在主线程结束时此线程也会自动结束...,但请注意它们的使用方式 7.建议使用CancellationTokenSource(s)进行超时管理时总是释放(dispose) 用于进行超时的CancellationTokenSources,如果释放

4.6K20

C#异步使用要点(翻译)

异步操作时需要注意的要点 1.使用异步方法返回值应当避免使用void 在使用异步方法中最好不要使用void当做返回值,无返回值也应使用Task作为返回值,因为使用void作为返回值具有以下缺点 无法得知异步函数的状态机在什么时候执行完毕...长时间运行的工作是指在应用程序生命周期执行后台工作的线程,如:执行processing queue items,执行sleeping,执行waiting或者处理某些数据,此类线程建议使用Task.Run...方法执行,因为Task.Run方法是将任务在线程池内进行排队执行,如果线程池线程进行长时间堵塞,会导致线程池增长,进而浪费性能,所以如果想要运行长时间的工作建议直接创建一个新线程进行工作 下面这个例子就利用了线程池执行长时间的阻塞工作...{ var thread = new Thread(ProcessQueue) { // 设置线程为背后线程,使得在主线程结束时此线程也会自动结束...,但请注意它们的使用方式 7.建议使用CancellationTokenSource(s)进行超时管理时总是释放(dispose) 用于进行超时的CancellationTokenSources,如果释放

3.3K50

.NET 内存泄漏的争议

在阅读本文前,如果你对 GC 分代算法还不了解,建议先阅读我的上一篇文章:小心使用 Task.Run 终篇解惑。...(100); // 模拟耗时操作 }); } ~MyClass() { Console.WriteLine("MyClass instance...我特意用 Test() 方法包装了一下 MyClass 实例的创建和调用,当 Test() 方法执行结束时,myClass 对象则变成了不再需要使用的对象。...如果在 while 循环内不断执行强制回收或者在强制回收前等待足够长的时间,保证 Task.Run 执行完,myClass 对象当然会被回收,因为此时它不存在被不可回收的资源捕获的成员,这点我本以为不需要示例演示大家应该也是这么认为的...我认为这也是定义问题,站在操作系统的视角和.NET托管堆的视角自然会得到不一样的理解。 就像最近头条上很多人对 1=0.999...

49120

从 ThreadLocal 到 AsyncLocal

前些天跟大佬们在群里讨论如何在不使用构造函数,增加方法参数的情况下把一个上下文注入到方法内部使用,得出的结论是 AsyncLocal 。...下面简单演示一下:threadLocal 初始值为1,然后启动多个线程对这个变量进行修改,最后主线程等待1秒,保证其它线程都执行成功后再次打印threadLocal的值。...我们现在更多的时候会使用 async/await Task 来帮我们做多线程异步操作。...这个时候我们的 ThreadLocal 就会力不从心了,让我们改造一下代码:我们把 new Thread 全部改造成 Task.Run执行修改变量的操作。...Dispose(); } } } 假设我们已经有了 Func1 方法,现在在破坏任何接口约束的情况下可以把 MyContext 直接通过静态变量 MyContext.Current

45720

关于同步方法里面调用异步方法的探究

首先我们来看一下,在 void里调用 async 方法,并且要等待async的结果出来之后,才能进行后续的操作。...没有任何问题。看起来,这样写完全没有问题啊,不报错,运行也是正常的。 接下来,我们修改一下代码,让代码更加接近生产环境的状态。...这个时候 A 会挂起,一直等 B 结束,B被释放,然后A继续执行剩下的过程。这样执行一次Producer 会用到两个线程,并且A 一直挂起,一直工作,一直在等B。这个时候线程A 就会阻塞。...但是糟糕又来了10个Task,需要20个线程,而之前释放的线程已经不足以让任何一个Task去执行Process了,因为这些不足的线程都被分配到了Producer上,没有线程再可以去执行Process了(...第二种情况:在同步方法里调用异步方法,wait() 如果这个异步方法进入的是global Task 则在线程饥饿的情况下,也会发生死锁的情况。

2.5K30

.NET 6.0 中的 await 原理浅析

"); await Task.Run(Work); Console.WriteLine("After Task.Run"); } static void...this.AddTaskContinuationComplex(tc, addBeforeOthers)); } 这里很清楚的看到,尝试把状态机对象(实际是状态机的包装类),赋值到 Task.m_continuationObject, 如果操作失败...= null) { action(); return; } } 很明显 this.InnerInvoke 就是执行了最开始 Task.Run(Work)...),若操作失败,直接把状态机对象压入线程池队列,等待调度 线程池线程调度任务完成后,会判断 Task.m_continuationObject 有值,直接执行它的 MoveNext 备注 状态机实现中,...尝试修改 Task.m_continuationObject,可能会失败, 就会直接把状态机对象压入线程池, 但是线程池调度,都是判断是不是 Task 类型么, 其实状态机的包装类是 Task 的子类

13620

UWP编程基础

Task 使用Task.Run方法在线程池上创建新的后台线程,并返回Task句柄。...命名空间: System.Threading.Tasks 例如,在后台进行登录操作 Task.Run(() => _Login(username, password)); 异步方法 使用Task可以在后台执行操作...在检测登录信息前,将按钮设置为不可用状态,使用await修饰的Task语句,将检测登录信息的函数放在后台执行,并中断当前代码,当_Login方法结束时,程序从中断处继续执行,将按钮设置为可用。...值得注意的是,一旦lambda表达式里的代码开始执行,该函数就会立即返回,因此不应该在lambda表达式中进行需要等待的操作,例如请求用户输入。...预编译语句包含数据的值,并且会在填入值之前进行语法分析,之后填入的值即使包含了SQL关键字也仍然会被当成字符串处理 在SQL语句中以”@”开头的字符串代替原本值的位置,并使用AddWithValue(

51910

在有 UI 线程参与的同步锁(如 AutoResetEvent)内部使用 await 可能导致死锁

for (var i = 0; i < 100; i++) { Task.Run(() => Do()); } // 主线程执行与后台线程并发竞争,也不会死锁。...walterlv is a 逗比 以上代码最关键的使用锁进行同步的地方是 Do 函数,采用了非常典型的防止方法重入的措施: 1 2 3 4 5 6 7 8 9 // 获得锁 try { // 执行某个需要线程安全的操作...} finally { // 释放锁 } 我们设置了线程池最小线程数为 100,这样在使用 Task.Run 进行并发的时候,一次能够开启 100 个线程来执行 Do 方法。...然而,此时 UI 线程正卡死在 _resetEvent.WaitOne();,于是根本没有办法执行 BeginInvoke 中的操作,也就是 await 之后的代码。...如有任何疑问,请 与我联系 ([email protected]) 。

17240
领券