Tag: 并发

什么.NET 4.0 System.Collections.Concurrent集合在function中添加到.NET 3.0 SynchronizedCollection?

.NET 4.0引入了System.Collections.Concurrent命名空间: “ System.Collections.Concurrent命名空间提供了几个线程安全的集合类,每当多个线程同时访问集合时,应该使用它们代替System.Collections和System.Collections.Generic命名空间中的相应类型” BlockingCollection类 ConcurrentBag类 ConcurrentQueue类 ConcurrentDictionary类 OrderablePartitioner类 Partitioner类 IProducerConsumerCollection接口 SynchronizedCollection类(自.NET 3.0起可用): “提供一个线程安全的集合,其中包含generics参数指定的类型的对象作为元素” …位于System.Collections.Generic命名空间中。 那么,为什么SynchronizedCollection类是线程安全的而不是并发的? 具体是什么使SynchronizedCollectiongenerics类与System.Collections.Concurrent集合不同且不兼容? 更新:让我重新解释一个问题:属于System.Collections.Concurrent命名空间的所有generics集合中的共同点和区分新特性是什么,它在SynchronizedCollectiongenerics类中不存在(并且在使用时不可能)? 我将标题更改为“.NET 4.0 System.Collections.Concurrent集合在function中添加到.NET 3.0 SynchronizedCollection ?”。 但大多数情况下,我很想知道是什么让它无法在.NET 3.0的基础上进行 Update2 :关于说明: “这个问题可能已经有了答案: SynchronizedCollection和其他并发集合有什么区别? “ 答案是在我的问题的背景下混淆 – 新function是进化的(使用预4.0版function)还是革命性的(在.NET 4.0之前不可用)?

在什么条件下线程可以同时进入锁(监控)区域多次?

(问题修改):到目前为止,答案都包括一个线程重新进入锁定区域的线程,通过递归之类的东西,您可以在其中跟踪单个线程进入锁定两次的步骤。 但是有可能以某种方式,对于单个线程(可能来自ThreadPool,可能是由于定时器事件或异步事件或线程进入hibernate状态并在其他一些代码块中被唤醒/重用)以某种方式产生两个不同的地方彼此独立,因此,当开发人员通过简单地阅读他们自己的代码而没有想到它时,会遇到锁重入问题? 在ThreadPool类备注( 单击此处 )中,备注似乎表明睡眠线程应在不使用时重复使用,否则会因睡眠而浪费。 但是在Monitor.Enter参考页面上( 点击这里 ),他们会说“同一个线程在没有阻止的情况下不止一次调用Enter是合法的”。 所以我认为必须有一些我应该小心避免的东西。 它是什么? 如何让单个线程两次进入同一个锁定区域? 假设您有一些锁定区域,不幸的是很长时间。 这可能是现实的,例如,如果您访问已被分页的内存(或其他内容)。锁定区域中的线程可能会进入睡眠状态。 同一个线程是否有资格运行更多代码,这可能会意外地进入同一个锁定区域? 在我的测试中,以下内容不会使同一个线程的多个实例进入同一个锁定区域。 那么如何产生问题呢? 你究竟需要小心避免什么? class myClass { private object myLockObject; public myClass() { this.myLockObject = new object(); int[] myIntArray = new int[100]; // Just create a bunch of things so I may easily launch a bunch of Parallel things Array.Clear(myIntArray, 0, myIntArray.Length); […]

取消长时间运行任务后如何正确清理

我创建了一个类,其目的是抽象出对队列的并发访问的控制。 该类被设计为在单个线程上实例化,由多个线程写入,然后从后续单个线程读取。 我在类中生成了一个长时间运行的任务,它将执行阻塞循环并在项成功出列时触发事件。 我的问题是:我执行取消长时间运行的任务并随后清理/重置CancellationTokenSource对象的正确用法吗? 理想情况下,我希望能够在保持可用性以添加到队列的同时停止并重新启动活动对象。 我用Peter Bromberg的文章作为基础: C#4.0中的生产者/消费者队列和BlockingCollection 代码如下: using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; namespace Test { public delegate void DeliverNextQueuedItemHandler(T item); public sealed class SOQueueManagerT { ConcurrentQueue _multiQueue; BlockingCollection _queue; CancellationTokenSource _canceller; Task _listener = null; public event DeliverNextQueuedItemHandler OnNextItem; public bool IsRunning { get; private set; } public int QueueSize […]

当与ConcurrentDictionary 一起使用时,C#LINQ OrderBy线程是否安全?

我的工作假设是,当与System.Collections.Concurrent集合(包括ConcurrentDictionary )一起使用时,LINQ是线程安全的。 (其他Overflowpost似乎同意: 链接 ) 但是,对LINQ OrderBy扩展方法的实现的检查表明,对于实现ICollection的并发集合的子集(例如ConcurrentDictionary ),它似乎不是线程安全的。 OrderedEnumerable GetEnumerator ( 此处为source )构造一个Buffer结构的实例( 此处为source ),它尝试将集合转换为ICollection ( ConcurrentDictionary实现),然后执行一个collection.CopyTo,其数组初始化为集合的大小。 因此,如果在OrderBy操作期间ConcurrentDictionary (在这种情况下为具体ICollection )的大小增加,在初始化数组和复制到它之间,此操作将抛出。 以下测试代码显示此exception: (注意:我很欣赏在一个线程安全的集合上执行一个OrderBy ,这个集合在你下面发生变化并没有那么有意义,但我不认为它应该抛出) using System; using System.Collections.Concurrent; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace Program { class Program { static void Main(string[] args) { try { int loop = 0; while (true) //Run many loops […]

如何测试线程安全

您对如何测试multithreading应用程序有什么建议吗? 我知道,线程错误很难捕获,它们可能随时发生 – 或者根本不发生。 测试很困难,结果永远不会确定。 当然最好仔细设计和编程并发模块。 尽管如此 – 我不想忽略测试方面。 因此,运行大量同时处理相同项目的线程有时会调用线程错误。 任何想法或最佳实践,以获得隐藏线程错误的高命中率? (我正在使用.Net / C#)

多个线程将元素添加到一个列表。 为什么列表中的项目总是少于预期?

以下代码解释了我的问题。 我知道列表不是线程安全的。 但是这个潜在的“真实”原因是什么? class Program { static void Main(string[] args) { List strCol = new List(); for (int i = 0; i { AddElements(strCol); }).ContinueWith((t) => { WriteCount(strCol, id.ToString()); }); } Console.ReadLine(); } private static void WriteCount(List strCol, string id) { Console.WriteLine(string.Format(“Task {0} is done. Count: {1}. Thread ID: {2}”, id, strCol.Count, Thread.CurrentThread.ManagedThreadId)); } private […]

Threadpool程序在更快的服务器上运行得慢得多

upd我现在认为我的问题的根源不是“线程化”,因为我在程序的任何一点都观察到减速。 我认为在使用2个处理器时我的程序执行速度较慢可能是因为两个处理器需要在彼此之间“通信”。 我需要做一些测试。 我将尝试禁用其中一个处理器,看看会发生什么。 ==================================== 我不确定这是否是C#问题,可能更多关于硬件,但我认为C#最合适。 我使用便宜的DL120服务器,我决定升级到更昂贵的2处理器DL360p服务器。 出乎意料的是,我的C#程序在新服务器上的运行速度大约慢了2倍,这应该要快几倍。 我处理了大约60台仪器的FAST数据。 我为每个乐器创建了单独的任务,如下所示: BlockingCollection updatesQuery; if (instrument2OrderUpdates.ContainsKey(instrument)) { updatesQuery = instrument2OrderUpdates[instrument]; } else { updatesQuery = new BlockingCollection(); instrument2OrderUpdates[instrument] = updatesQuery; ScheduleFastOrdersProcessing(updatesQuery); } orderUpdate.Checkpoint(“updatesQuery.Add”); updatesQuery.Add(orderUpdate); } private void ScheduleFastOrdersProcessing(BlockingCollection updatesQuery) { Task.Factory.StartNew(() => { Instrument instrument = null; OrderBook orderBook = null; int lastRptSeqNum = -1; while (!updatesQuery.IsCompleted) […]

如何处理Task.Runexception

我从Task.Run中捕获exception时遇到了问题。我更改了代码并解决了问题。 我愿意弄清楚在这两种方式下处理Task.Run中的exception有什么区别: 在Outside函数中我无法捕获exception但在Inside中我可以捕获它。 void Outside() { try { Task.Run(() => { int z = 0; int x = 1 / z; }); } catch (Exception exception) { MessageBox.Show(“Outside : ” + exception.Message); } } void Inside() { Task.Run(() => { try { int z = 0; int x = 1 / z; } catch (Exception […]

Java ExecutorService.newSingleThreadExecutor()的C#等价物,或者:如何序列化对资源的multithreading访问

我的代码中有几种情况,各种线程可以创建工作项,由于各种原因,不应该并行完成。 我想确保工作以FIFO方式完成,无论它来自哪个线程。 在Java中,我将工作项放在单线程ExecutorService ; 在C#中是否有等价物? 我用Queue和一堆lock(){}块拼凑了一些东西,但是能够使用现成的和经过测试的东西会很好。 更新:有没有人有System.Threading.Tasks的经验? 它有这种解决方案吗? 我正在写一个Monotouch应用程序,所以谁知道我是否能找到它可以开始工作的它的后向版本,但它至少是为未来考虑的事情。 更新#2对于不熟悉我正在谈论的Java库的C#开发人员,基本上我想要一些东西让各个线程交出工作项,这样所有这些工作项都将在一个线程上运行(这不是任何一个调用线程)。 更新,6/201 :如果我现在正在构建一个类似的系统,我可能会根据Matt Craig的回答使用Reactive Extensions 。 我离开Zachary Yates回答了被接受的答案 ,因为如果你在Rx中思考,你可能甚至都不会问这个问题,我认为ConcurrentQueue更容易进入前Rx程序。

以只读方式返回集合

我在一个multithreading环境中有一个对象来维护一组信息,例如: public IList Data { get { return data; } } 我目前有return data; 由ReaderWriterLockSlim包装,以保护集合免受共享冲突。 但是,为了更加确定,我想将集合作为只读方式返回,这样调用代码就无法对集合进行更改,只能查看已经存在的集合。 这是可能吗?