用Task代替Thread时,Abort和IsBackground两个属性的处理。。

phommy 2014-06-13 05:49:30
在Task里没有找到能代替这两个属性的方法。。。

场景的话,比如:

Abort:我在子线程或Task里执行一个同步操作(比如Semaphore.WaitOne或者等一个sql执行完毕),主进程不想等了,就可以随时Abort掉。但Task中并不存在判断CancellationTokenSource的时机

IsBackground:这个场景就简单了,主线程退出时,自动终止没完成的Task,这个可以直接通过一个属性做到吗?如果不能,常规处理方式是什么呢?
...全文
940 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
ljz_08 2015-04-07
  • 打赏
  • 举报
回复
楼主我也遇到一样的需求。不知道你现在解决了没有?分享一下
暈哥 2014-06-16
  • 打赏
  • 举报
回复
“线程不是说停就停” 说的就是你这种情况,即使是Abort也会等sql执行返回才会停止; 另外Task也不太适合这种情况,一般用来执行“短小精悍”的任务; 不管是任何形式的线程都不该由其他线程来停止,而是自身控制退出,对外提供接口(CancellationToken或bool标识) 如果非得中途取消sql执行可以试试前台线程+事物。
phommy 2014-06-16
  • 打赏
  • 举报
回复
引用 1 楼 lineages 的回复:
请忘记Abort这个方法,你说的“不存在判断CancellationTokenSource的时机”是在纠结什么,至于你说的“可以随时Abort掉”那是你想当然,线程并不是说停就停的,我们不要试图去控制线程,应该去控制交给线程处理的任务。 Task的出现就是为了解决线程池太鸡肋的问题,生来就是后台线程。
谢谢~ 第2个问题你这样说我就懂了。 第1个问题,比如说sql server的查询分析器上有个“停止”按钮,在执行用时很长的sql时可以随时按这个按钮中止掉。如果用 Thread实现,就是在子线程里执行 ExecuteScalar,用户在界面进程点“停止”时杀掉子进程就行了;换用Task要怎么实现呢?
phommy 2014-06-16
  • 打赏
  • 举报
回复
引用 4 楼 yun738243875 的回复:

			CancellationTokenSource cts = new CancellationTokenSource();
			Task<int> t = new Task<int>(() => Sum(cts.Token, 1000), cts.Token);
			t.Start();
			Console.WriteLine("Press <Enter> to cancel the operation");
			Console.Read();
			cts.Cancel();
			try {
				t.Wait();
			} catch (AggregateException ex) {
				ex.Handle(p => p is OperationCanceledException);
				Console.WriteLine("Sum was Canceled.");
			}
			Thread.Sleep(10000);

static int Sum(CancellationToken token, int n) {
			int sum = 0;
			for (; n > 0; n--) {
				token.ThrowIfCancellationRequested();
				checked {
					sum += n;
				}
				Console.Write("{0} ", n);
				Thread.Sleep(1000);
			}
			return sum;
		}
楼主懂了么?主要利用CancellationToken在任务中如果调用它的Cancel方法会抛出AggregateException异常,主线程只要捕获这个异常并且处理他,就说明任务被取消了。
你的例子我懂了,但我需要更“一般”的写法。。。在你的例子中,最耗时的部分“恰好”是你自己的一个循环,所以你才可以在每次循环中都判断一次任务是否被取消了 (利用token.ThrowIfCancellationRequested) 。 但如果最耗时的部分不是我的代码怎么办呢,比如我就是调用了.net执行sql语句的操作,而这个操作相当耗时、我也没有办法要求他去隔段时间调用一下 token.ThrowIfCancellationRequested 。。。
yun738243875 2014-06-16
  • 打赏
  • 举报
回复

			CancellationTokenSource cts = new CancellationTokenSource();
			Task<int> t = new Task<int>(() => Sum(cts.Token, 1000), cts.Token);
			t.Start();
			Console.WriteLine("Press <Enter> to cancel the operation");
			Console.Read();
			cts.Cancel();
			try {
				t.Wait();
			} catch (AggregateException ex) {
				ex.Handle(p => p is OperationCanceledException);
				Console.WriteLine("Sum was Canceled.");
			}
			Thread.Sleep(10000);

static int Sum(CancellationToken token, int n) {
			int sum = 0;
			for (; n > 0; n--) {
				token.ThrowIfCancellationRequested();
				checked {
					sum += n;
				}
				Console.Write("{0} ", n);
				Thread.Sleep(1000);
			}
			return sum;
		}
楼主懂了么?主要利用CancellationToken在任务中如果调用它的Cancel方法会抛出AggregateException异常,主线程只要捕获这个异常并且处理他,就说明任务被取消了。
暈哥 2014-06-13
  • 打赏
  • 举报
回复
请忘记Abort这个方法,你说的“不存在判断CancellationTokenSource的时机”是在纠结什么,至于你说的“可以随时Abort掉”那是你想当然,线程并不是说停就停的,我们不要试图去控制线程,应该去控制交给线程处理的任务。 Task的出现就是为了解决线程池太鸡肋的问题,生来就是后台线程。

110,530

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧