设为首页 加入收藏

TOP

Threads(异步和多线程)(四)
2019-09-23 11:16:38 】 浏览:128
Tags:Threads 异步 线程
is {name} 开始 ThreadId={Thread.CurrentThread.ManagedThreadId.ToString(
"00")}"); Thread.Sleep(new Random().Next(50, 100)); if (name.Equals("btnThreadCore_Click_11")) { throw new Exception("btnThreadCore_Click_11异常"); } else if (name.Equals("btnThreadCore_Click_12")) { throw new Exception("btnThreadCore_Click_12异常"); } else if (name.Equals("btnThreadCore_Click_13")) { cts.Cancel(); } if (!cts.IsCancellationRequested) { Console.WriteLine($"This is {name}成功结束 ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}"); } else { Console.WriteLine($"This is {name}中途停止 ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}"); return; } } catch (Exception ex) { Console.WriteLine(ex.Message); cts.Cancel(); } }, cts.Token)); } //1 准备cts 2 try-catch-cancel 3 Action要随时判断IsCancellationRequested //尽快停止,肯定有延迟,在判断环节才会结束 Task.WaitAll(taskList.ToArray()); //如果线程还没启动,能不能就别启动了? //1 启动线程传递Token 2 异常抓取 //在Cancel时还没有启动的任务,就不启动了;也是抛异常,cts.Token.ThrowIfCancellationRequested } catch (AggregateException aex) { foreach (var exception in aex.InnerExceptions) { Console.WriteLine(exception.Message); } } catch (Exception ex) { Console.WriteLine(ex.Message); } View Code

临时变量:

 for (int i = 0; i < 5; i++)
 {
     Task.Run(() =>
     {
         Console.WriteLine($"This is btnThreadCore_Click_{i} ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
     });
 }

 

 为什么运行结果后,都是5呢?

  临时变量问题,线程是非阻塞的,延迟启动的;线程执行的时候,i已经是5了

那么该如何解决呢?

  每次都声明一个变量k去接收,k是闭包里面的变量,每次循环都有一个独立的k,5个k变量  1个i变量

for (int i = 0; i < 5; i++)
{
    int k = i;
    Task.Run(() =>
    {
        Console.WriteLine($"This is btnThreadCore_Click_{i}_{k} ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
    });
}

这样再运行,结果就正常了。

 

 线程安全&lock:

线程安全:如果你的代码在进程中有多个线程同时运行这一段,如果每次运行的结果都跟单线程运行时的结果一致,那么就是线程安全的

线程安全问题一般都是有全局变量/共享变量/静态变量/硬盘文件/数据库的值,只要多线程都能访问和修改

发生是因为多个线程相同操作,出现了覆盖,怎么解决?

1 Lock解决多线程冲突

Lock是语法糖,Monitor.Enter,占据一个引用,别的线程就只能等着

推荐锁是private static readonly object,

 A不能是Null,可以编译不能运行;

B 不推荐lock(this),外面如果也要用实例,就冲突了

//Test test = new Test();
//Task.Delay(1000).ContinueWith(t =>
//{
//    lock (test)
//    {
//        Console.WriteLine("*********Start**********");
//        Thread.Sleep(5000);
//        Console.WriteLine("*********End**********");
//    }
//});
//test.DoTest();

//C 不应该是string; string在内存分配上是重用的,会冲突
//D Lock里面的代码不要太多,这里是单线程的
Test test = new Test();
string student = "水煮鱼";
Task.Delay(1000).ContinueWith(t =>
{
    lock (student)
    {
        Console.WriteLine("*********Start**********");
        Thread.Sleep(5000);
        Console.WriteLine("*********End**********");
    }
});
test.DoTestString();
//2 线程安全集合
//System.Collections.Concurrent.ConcurrentQueue<int>

//3 数据分拆,避免多线程操作同一个数据;又安全又高效

for (int i = 0; i < 10000; i++)
{
    this.iNumSync++;
}
for (int i = 0; i < 10000; i++)
{
    Task.Run(() =>
    {
        lock (Form_Lock)//任意时刻只有一个线程能进入方法块儿,这不就变成了单线程
        {
首页 上一页 1 2 3 4 5 下一页 尾页 4/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C#程序员在老项目中用到VB遇到的.. 下一篇C#面向对象之继承

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目