定时器上的异步任务。如何避免重叠?
Asynchronous tasks on a Timer. How to avoid overlapping?
我正在使用计时器每 {n} 秒向服务器请求一次消息。
我收到一些异常,我认为这些异常与我收集的消息不是线程安全的有关。
我闻到有腥味,但我不确定最好的处理方法是什么。
代码看起来类似于:
ThreadPool.QueueUserWorkItem(delegate
{
while (true)
{
try
{
DoSomething1();
DoSomething2();
}
catch (Exception ex)
{
LogManager.GetLogger(GetType()).Error("Exception caught in " + GetType().Name, ex);
}
finally
{
Thread.Sleep(TimeSpan.FromSeconds(20));
}
}
});
private void DoSomething1()
{
messages.AddRange(server.GetMessages());
ParseMessages();
messages.Clear();
}
有时在执行 AddRange 时出现此错误:
System.ArgumentException: Source array was not long enough. Check
srcIndex and length, and the array's lower bounds. at
System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array
destinationArray, Int32 destinationIndex, Int32 length, Boolean
reliable) at System.Collections.Generic.List1.set_Capacity(Int32
value) at System.Collections.Generic.List
1.EnsureCapacity(Int32
min) at System.Collections.Generic.List1.InsertRange(Int32 index,
IEnumerable
1 collection) at
System.Collections.Generic.List1.AddRange(IEnumerable
1 collection)
我认为这是因为消息列表在另一个计时器调用时被修改了?
如果您在多个线程中有多个生产者,请使用某种锁定机制(如 lock
关键字)或更好地使用 Thread-Safe Collections 中的线程安全集合。还要确保 server.GetMessages()
没有返回 null
.
您似乎可以使用 ConcurrentQueue<T>
(自 .NET 4.0 以来的开箱即用的内置线程安全集合)来执行相同的工作。如果您正在解析消息,您可能会按顺序解析它们,因此,FIFO 应该适合您。
我正在使用计时器每 {n} 秒向服务器请求一次消息。 我收到一些异常,我认为这些异常与我收集的消息不是线程安全的有关。
我闻到有腥味,但我不确定最好的处理方法是什么。
代码看起来类似于:
ThreadPool.QueueUserWorkItem(delegate
{
while (true)
{
try
{
DoSomething1();
DoSomething2();
}
catch (Exception ex)
{
LogManager.GetLogger(GetType()).Error("Exception caught in " + GetType().Name, ex);
}
finally
{
Thread.Sleep(TimeSpan.FromSeconds(20));
}
}
});
private void DoSomething1()
{
messages.AddRange(server.GetMessages());
ParseMessages();
messages.Clear();
}
有时在执行 AddRange 时出现此错误:
System.ArgumentException: Source array was not long enough. Check srcIndex and length, and the array's lower bounds. at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable) at System.Collections.Generic.List
1.set_Capacity(Int32 value) at System.Collections.Generic.List
1.EnsureCapacity(Int32 min) at System.Collections.Generic.List1.InsertRange(Int32 index, IEnumerable
1 collection) at System.Collections.Generic.List1.AddRange(IEnumerable
1 collection)
我认为这是因为消息列表在另一个计时器调用时被修改了?
如果您在多个线程中有多个生产者,请使用某种锁定机制(如 lock
关键字)或更好地使用 Thread-Safe Collections 中的线程安全集合。还要确保 server.GetMessages()
没有返回 null
.
您似乎可以使用 ConcurrentQueue<T>
(自 .NET 4.0 以来的开箱即用的内置线程安全集合)来执行相同的工作。如果您正在解析消息,您可能会按顺序解析它们,因此,FIFO 应该适合您。