当前位置: 首页 > news >正文

C#异步协同常用例子

  • 携带私货(数据)的异步协同
    比如主线程(UI线程)等待Task或Task等待主线程把数据传给它,用TaskCompletionSource最适合不过,例如主线程等待Task返回数据,除了将task定义为async task 子方法,还可以这样做:
 var signal=new TaskCompletionSource<string>();_=Task.Run(() =>{Console.WriteLine("task started, waiting for 5 seconds...");Thread.Sleep(5000);signal.SetResult("task results.");Console.WriteLine("Task finished.");});Console.WriteLine("Main thread is waiting for the Task to complete...");var result=await signal.Task;Console.WriteLine($"task result: {result}");

当然,反过来,Task里面等待主线程传值也是可以的:

var signal = new TaskCompletionSource<string>();
_ = Task.Run(async () =>
{Console.WriteLine("task is waiting for main thread signal...");var result = await signal.Task;Console.WriteLine($"result: {result}");            Console.WriteLine("Task finished.");
});
Console.WriteLine("Main thread is doing something, waiting for 5 seconds...");
Thread.Sleep(5000);
signal.SetResult("data from main thread.");
  • 多次协同通知

用AutoResetEvent

var resetEvent = new AutoResetEvent(false);
var task = Task.Run(() =>
{Console.WriteLine("task started, waiting main thread...");resetEvent.WaitOne();Console.WriteLine("got main thread signal,doing something..");Console.WriteLine("wait again..");resetEvent.WaitOne();Console.WriteLine("got again..");
});
Console.WriteLine("Main thread is doing something, waiting for 5 seconds...");
Thread.Sleep(3000);
resetEvent.Set(); //set 1
Console.WriteLine("Main thread doing something again...");
Thread.Sleep(3000);
resetEvent.Set(); //set 2
task.Wait();
Console.WriteLine("all done.");
resetEvent.Close();
  • 多个任务等待
    最典型的主线程等待多任务完成 ,用CountdownEvent实现
int TaskCount = 10;
var countDown=new CountdownEvent(TaskCount);
List<Task> TaskList = new List<Task>();   
for (int i = 0; i < TaskCount; i++)
{int curI = i;Random rnd = new Random();Task task = Task.Run(() =>{Console.WriteLine($"Task {curI + 1} started");Thread.Sleep(rnd.Next(5000));Console.WriteLine($"Task {curI + 1} finished");countDown.Signal();} );TaskList.Add(task);
}
Console.WriteLine("Main thread is waiting");
countDown.Wait();//等待所有任务结束
Console.WriteLine("All done.");

当然,如果只是等待一组任务的完成,可以用Task.WaitAll(Task[]);

 int TaskCount = 10;List<Task> TaskList = new List<Task>();for (int i = 0; i < TaskCount; i++){int curI = i;Random rnd = new Random();Task task = Task.Run(() =>{Console.WriteLine($"Task {curI + 1} started");Thread.Sleep(rnd.Next(5000));Console.WriteLine($"Task {curI + 1} finished");});TaskList.Add(task);}Console.WriteLine("Main thread is waiting");Task.WaitAll(TaskList.ToArray());Console.WriteLine("All done.");
  • 多线程共享数据

    volatile关键字的应用

    volatile 确保被修饰的变量透明,防止因为编译器或执行程序对指令重排序导致拿不到最新的值。
    可以修饰所有引用类型 (Reference types):string、object、class 等。

    整数类型 (Integer types):sbyte, byte, short, ushort, int, uint。

    布尔类型 (Boolean type):bool。

    字符类型 (Character type):char。

    浮点类型 (Floating-point types):float。

    枚举类型 (Enum types):只要其基础类型是上述可修饰的类型之一。

    指针类型 (Pointer types):IntPtr, UIntPtr。

    唯独double,long和struct结构体不能用它 ,这些结构体应该用lock或Interlocked

    lock操作

比如对银行帐户的存取操作,先定义类,类里面定义锁对象,对balance的修改都在lock里面进行以确保多线程同时操作的情况下保证balance的正确性

public class BankAccount
{private decimal balance = 0;// 创建一个专用的私有锁对象,通常命名为 lockObjectprivate readonly object lockObject = new object();  //为什么要单独定义一个lock对象??那是因为要将锁定范围最小化public void Deposit(decimal amount){// 锁定 lockObject,确保只有当前线程能进入这个代码块lock (lockObject){balance += amount;}}public void Withdraw(decimal amount){// 锁定 lockObject,与 Deposit 方法共享同一个锁lock (lockObject){balance -= amount;}}public decimal GetBalance(){return balance;}
}

Interlocked

Common Interlocked Methods
Method Description
Interlocked.Increment(ref int location) Atomically increments a 32-bit signed integer.
Interlocked.Decrement(ref int location) Atomically decrements a 32-bit signed integer.
Interlocked.Add(ref int location, int value) Atomically adds a value to a 32-bit signed integer.
Interlocked.Exchange(ref int location1, int value) Atomically sets a variable to a specified value and returns the original value.
Interlocked.CompareExchange(ref int location1, int value, int comparand) Atomically compares a variable to a comparand and, if they are equal, sets the variable to a new value. This is a common pattern for lock-free programming.

适合多个任务同时更新某个变量

public class Counter
{private static int _count = 0;public void DoWork(){// Using Interlocked ensures that the increment operation is atomic.// It's a thread-safe way to update the shared _count variable.Interlocked.Increment(ref _count);// Instead of: _count++; // This is NOT thread-safe}public int Count => _count;
}...var counter = new Counter();var tasks = new Task[100];for (int i = 0; i < 100; i++){tasks[i] = Task.Run(() => counter.DoWork());}Task.WaitAll(tasks);Console.WriteLine($"Final count: {counter.Count}");
  • 任务中更新UI

    这个最常用,经典用法,在Task里面:

   if (prg.InvokeRequired)
{// 在非UI线程调用时,切换到UI线程执行prg.BeginInvoke(new Action(() => prg.je100()));  
}

为什么用BeginInvoke而不是this.Invoke?? BeginInvoke不需要等待,只是发出渲染指令,能避免死锁问题。

http://www.dtcms.com/a/397886.html

相关文章:

  • Flutter 中使用 Color 的最优方案
  • 一半都有哪些做影视外包的网站怎么做网站的签约编辑
  • Qt QEventLoop的使用的一个问题讨论
  • 保定网站seo技术wordpress主题左目录
  • net网站开发做手工简笔上海手机网站建设
  • 做地图的网站湖北专业网站建设市面价
  • 拜师做网站网站短链接生成
  • 用狐狸做logo的网站虾皮跨境电商注册多少钱
  • 东莞化工网站建设网站的思维导图怎么做
  • 公司网站制作银川微信投票网站怎么做
  • 英国零售电商网站开发好点的开发网站的公司
  • 韶关最新消息厦门关键词排名优化
  • 家居网站建设流程企业网站是怎么建站的
  • 国外的域名注册网站哪个好wordpress的使用方法
  • 网站建设包涵哪些领域可以做推广的网站
  • 东莞如何搭建网站建设护肤品营销策划方案
  • 国外网站推广平台有哪些公司最新新闻热点事件2022年1月
  • 网站建设德语企业网站首页的实现
  • 怎么样建设自己的网站php网站模板制作软件
  • 潍坊建设网站多少钱装修公司加盟合作模式
  • 国内产品设计网站wordpress黑镜百度云盘
  • 医院网站建设模板怎么让网站排名上去
  • 西安市做网站怎么建一个卖东西的网站
  • 平台推广策划方案seo推广培训资料
  • 电子商务网站的基础建设重庆建设厂招聘信息网站
  • 济宁网站建设平台o2o网站咋建设
  • 做网站接私单百度精简版入口
  • 软件开发人员招聘seo都用在哪些网站
  • 网站建设服务详细解读优化一个网站多少钱
  • 网站界面用什么做的服装设计手稿