- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个 Windows 服务,它使用带有回调的 System.Threading.Timer 来更新端点,如下所示:
UpdateEndpointTimer = new Timer(
new TimerCallback(UpdateSBEndpoints),
Endpoint.Statuses.Online,
EndpointUpdateFrequency,
EndpointUpdateFrequency);
我的更新方法大致如下:
private void UpdateSBEndpoints(object state)
{
...
using (var context = new TestHarnessContext())
{
var endpoints = context.Endpoints.Where(p =>
p.Binding == Endpoint.Bindings.ServiceBus
&& p.State == Endpoint.States.Enabled
&& p.Status != status).ToList();
foreach (var endpoint in endpoints)
{
//Do stuff here
}
...
}
现在,由于计时器使用 ThreadPool 中的线程来触发回调,我需要采取措施来控制线程。当多个线程可以在第一个线程完成工作之前从数据库中获取相同的端点时,就会出现一个特定的问题,这会导致在 foreach 循环中完成重复的工作。
我知道该问题有两种可能的解决方案,我想知道哪一种更好,更适合使用。解决方案是 ConcurrentDictionary
和 ManualResetEvent
。
在第一种情况下,我会把它放在我的 foreach 循环中,以确保一次只有一个线程可以在给定的端点上运行:
if (EndpointsInAction.TryAdd(endpoint.Id, endpoint.Id) == false)
// If we get here, another thread has started work with this endpoint.
return;
...
//Do stuff with the endpoint, once done, remove its Id from the dictionary
...
int id;
EndpointsInAction.TryRemove(endpoint.Id, out id);
在第二种情况下,我会像这样控制线程:
protected ManualResetEvent PubIsBeingCreated { get; set; }
protected ManualResetEvent SubIsBeingCreated { get; set; }
...
this.PubIsBeingCreated = new ManualResetEvent(true);
this.SubIsBeingCreated = new ManualResetEvent(true);
...
foreach (var endpoint in endpoints)
{
if (!this.PubIsBeingCreated.WaitOne(0))
// If we get here, another thread has started work with this endpoint.
return;
try
{
// block other threads (Timer Events)
PubIsBeingCreated.Reset();
// Do stuff
}
...
finally
{
// Restore access for other threads
PubIsBeingCreated.Set();
}
}
现在这两种方法似乎都有效我想知道哪种方法更适合使用(效率更高?)。我倾向于使用 ConcurrentDictionary
,因为它允许更好地过滤线程,即不允许两个线程与特定端点一起工作,而不允许两个线程与特定端点一起工作类型(ManualResetEvents 中的发布和订阅)。可能有其他解决方案优于我的解决方案,因此我们将不胜感激。
最佳答案
在任何情况下,您都不应为此目的使用 ManualResetEvent
。使用提供更高级别抽象的对象总是更好,但即使您想在低级别控制它,也可以使用 .NET 的 Monitor 类(通过 lock
语句和 Monitor .Wait()
和 Monitor.Pulse()
方法比使用 ManualResetEvent
更好。
您似乎有一个相当标准的生产者/消费者场景。在那种情况下,在我看来,您最好使用 ConcurrentQueue
而不是 ConcurrentDictionary
。您的生产者会将事物排入队列,而您的消费线程会将它们从队列中取出以进行处理。
关于C# ConcurrentDictionary 与线程控制的 ManualResetEvent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26639150/
我在我的网络应用程序中创建了一个 ConcurrrentDictionary 作为应用程序对象。它在 session 之间共享。 (基本上用作存储库。) 有时,任何可用的 session 都会将新项目
ConcurrentDictionary.TryUpdate 方法需要与具有指定键的元素的值进行比较的 comparisonValue。但是如果我想做这样的事情: if (!_store.TryGet
如果我有一个 ConcurrentDictionary例如,我是否使用 Count 有关系吗?属性(property)或LINQ的Any() ?我宁愿写 dict.Any()而不是 dict.Coun
我正在使用并发字典来存储大约200万条记录,并且想知道如何初始化字典的并发级别。 MSDN页面的示例代码中具有以下注释: concurrencyLevel越高,可以在ConcurrentDiction
我正在使用 ConcurrentDictionary 来存储日志行,当我需要向用户显示它们时,我调用 ToList()生成一个列表。但奇怪的是,一些用户在列表中最先收到最近的行,而从逻辑上讲,他们应该
我发现这个 C# 扩展将 GetOrAdd 转换为 Lazy,我想对 AddOrUpdate 做同样的事情。 有人可以帮我将其转换为 AddOrUpdate 吗? public static cla
我对并发字典如何锁定他们的资源感到困惑。 例如,如果我运行一个方法来迭代字典中的每个项目并在一个线程中编辑它的值,然后我尝试从另一个线程读取一个键的值: 第二个线程会访问字典的快照吗? 如果没有,如果
我找不到有关 ConcurrentDictionary 类型的足够信息,因此我想在这里询问一下。 目前,我使用字典来保存由多个线程(来自线程池,因此没有确切数量的线程)不断访问的所有用户,并且它具有同
我在 Azure 应用服务上使用 MVC 5、ASP.NET 4.7 我正在使用 ConcurrentDictionary 对象来保存数据,以保存对数据源的多次调用。 关于其行为的几个问题: 1) 填
我想使用 ConcurrentDictionary 来检查之前是否添加了这个数据键,但看起来我仍然可以添加之前添加的键。 代码: public class pKeys {
我正在按照教程构建聊天客户端和服务器,现在我遇到了以下错误: Inconsistent accessibility: field type 'System.Collections.Concurrent
我正在考虑将类(单例)与使用 ConcurrentDictionary 实现的集合一起使用。此类将用作缓存实现 (asp.net/wcf)。 您如何看待从此类中显式公开这些集合与仅公开例如3 种方法(
有一个并发字典,它从不同的来源收集信息,每分钟刷新一次并将收集的数据传递给另一个处理程序。 var currentDictionarySnapshot = _currentDictionary; _c
我在 static 类中有一个静态 ConcurrentDictionary。在该类的静态构造函数中,我通过 Task.Run 调用一个私有(private)方法来无限循环遍历字典并删除已过期的项目,
我在 StackOverflow 上阅读了以下文章:ConcurrentBag - Add Multiple Items?和 Concurrent Dictionary Correct Usage但答
我存储这个类 public class Customer { public string Firstname { get; set; } public string Lastname
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 关于您编写的代码问题的问题必须在问题本身中描述具体问题 — 并且包括有效代码 以重现它。参见 SSC
我正在编写一些使用反射的代码。所以我试图将昂贵的反射处理缓存到 ConcurrentDictionary 中。但是,我想对并发字典应用限制,以防止存储旧的和未使用的缓存值。 我做了一些研究以了解如何限
好吧,所以我遇到了一个奇怪的小问题,坦率地说,我没有想法。我想把它扔出去看看我是否遗漏了我做错的东西,或者 ConcurrentDictionary 是否工作不正常。这是代码: (缓存是一个包含静态
我正在尝试使用 ConcurrentDictionary 来帮助完成过滤任务。 如果一个数字出现在列表中,那么我想将一个条目从一个字典复制到另一个。 但这部分的 AddOrUpdate 是不对的 -
我是一名优秀的程序员,十分优秀!