完全像Javascript一样的异步C#应用
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了完全像Javascript一样的异步C#应用,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3008字,纯文字阅读大概需要5分钟。
内容图文
![完全像Javascript一样的异步C#应用](/upload/InfoBanner/zyjiaocheng/662/c980fad672ca488f84a6220aedd72431.jpg)
在javascript中,我们可以为异步操作调用SetTimeout,而不必担心线程安全问题,因为javascript是单线程的,并且SetTimeout不会在新线程中执行代码块.
在C#中,我们可以使用Task类来使操作异步,如下所示.
Task.Factory.StartNew(()=> DoOperation());
但是据我所知,DoOperation可以在主线程或新线程中发生,而Task不允许我们决定是在新线程中还是在同一线程中.
新的异步功能不等同于SetTimeout.
如何在C#应用程序(如Javascript)中实现完全相同的功能?有没有一种方法可以将Console App配置为单线程(我记得这样的事情)
编辑:
考虑一下我正在处理的以下用例场景.它是简化版.
class Program
{
static BufferBlock<int> queue = new BufferBlock<int>();
static List<int> list = new List<int>();
static void Main(string[] args)
{
Task.WhenAll(Produce(), Consume()).ContinueWith(r=> Console.WriteLine("list count: "+list.Count));
Console.ReadKey();
}
public static async Task Produce()
{
var random = new Random();
for (int i = 0; i < 1000; i++)
{
var value = random.Next();
await queue.SendAsync(value);
await Task.Delay(random.Next(1, 4));
list.Add(value);//manipulate none thread safe object
Console.WriteLine("value produced " + value);
}
queue.Complete();
}
public static async Task Consume()
{
var random = new Random();
while (await queue.OutputAvailableAsync())
{
var value = await queue.ReceiveAsync();
//consume the value
await Task.Delay(random.Next(1, 4));
list.Remove(value);//manipulate none thread safe object
Console.WriteLine("value consumed " + value);
}
}
}
它基本上是生产者/消费者模式,生产者增加价值,而消费者消耗这些价值.我们通过此作业操作List对象,它不是线程安全的.
在任务列表的末尾计数应该为0,但这不是因为2个任务没有访问线程安全的List对象.我们当然可以像锁定一样以不同的方式处理线程安全问题,但是在我的用例中,它是不必要的,效率低下的,太多的锁定难以遵循并且容易陷入死锁问题.
@Asad和其他人指出了正确的方向,感谢大家.
解决方法:
如果仅要确保正在运行的线程不超过一个(并且不一定要在同一个线程上运行所有线程),则可以使用独占调度程序来执行此操作:
static void Main(string[] args)
{
var sch = new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler;
var tf = new TaskFactory(sch);
var t = tf.StartNew(() => Run()).Result;
t.Wait();
}
static async Task Run()
{
var start = DateTime.UtcNow;
var t = Task.Delay(1000).ContinueWith(_ =>
{
Console.WriteLine("I tried to log after 1 second, ended up logging after {0}", (DateTime.UtcNow - start).TotalSeconds);
});
Console.WriteLine("It has not yet been 1 second. I will hog the only thread available to demonstrate how I simulate JS behavior.");
Thread.Sleep(2000);
await t;
}
我正在使用ConcurrentExclusiveSchedulerPair.ExclusiveScheduler创建一个新的任务工厂,该工厂将用于运行主程序入口点.
如果运行此程序,您会注意到,即使计划将日志记录安排为1秒钟,它也会被阻塞,因为一个线程已经无所事事(这正是JS的行为方式).删除Sleep并按时调用超时回调.
最后,这是使用单线程异步方法模拟JS setTimeout行为的方法:
static async Task JSSetTimeout(int ms, Action callback, int waitResolution = 10)
{
var startTime = DateTime.UtcNow;
while ((DateTime.UtcNow - startTime).TotalMilliseconds < ms)
{
await Task.Delay(waitResolution);
}
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
callback();
}
内容总结
以上是互联网集市为您收集整理的完全像Javascript一样的异步C#应用全部内容,希望文章能够帮你解决完全像Javascript一样的异步C#应用所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。