从事件的无限 Parallel.Foreach 循环中取消令牌
Cancel Token from infinite Parallel.Foreach loop from an event
我写了一些代码,其中我使用 Parallel.Foreach 一些项目与无限循环并行工作,即每 60 秒后工作正常。
但是这里我的消息可以被用户随时更改,我需要用新消息重新处理。
为此,我需要取消无限 Parallel.Foreach 循环以重新处理更新的消息。
当我尝试重新处理 main 方法时,它对新消息工作正常,但它 运行ning 两次,因为之前的计划任务没有被取消。我假设我需要从 Parrallel.Foreach 循环中取消进程,然后重新 运行 以获取具有新计划的更新消息。
谁能帮我取消已经安排在下一个 60 秒的排队任务。
static void Main(string[] args)
{
List<RealTimeMessage> messages = GetRealTimeMessage();
Parallel.ForEach(messages, (message) =>
{
processMessage(message);
});
Console.ReadLine();
}
private static async void processMessage(RealTimeMessage message)
{
try
{
while (true)
{
await Task.Delay(TimeSpan.FromSeconds(60));
await Task.Run(() => ProceesRequest(message));
}
}
catch (Exception)
{
Console.WriteLine("Critical error");
}
}
private static List<RealTimeMessage> GetRealTimeMessage()
{
List<RealTimeMessage> realTimeMessages = new List<RealTimeMessage>();
realTimeMessages.Add(new RealTimeMessage { MessageText = "Message 4", IntervalTime = "1", MessageType = "AIDX", TimeOfDay = "" });
realTimeMessages.Add(new RealTimeMessage { MessageText = "Message 5", IntervalTime = "2", MessageType = "AMSX", TimeOfDay = "" });
return realTimeMessages;
}
private static void ProceesRequest(RealTimeMessage message)
{
// do domething
}
- 这是对
Parallel.ForEach
的误用,请改用 Task.WhenAll
- 不要在 ProcessMessage 中启动
Task
(这可能是故意的,但看起来像是一个错误)。
- 使用
CancellationToken
来取消一个任务
- 不要使用
async void
除非它是为了一个事件
- 方法名称使用标准大小写
- 不要使用
while(true)
使用 while (!token.IsCancellationRequested)
考虑到所有因素后,它看起来像这样
static async Task Main(string[] args)
{
var ts = new CancellationTokenSource();
var messages = GetRealTimeMessage();
var tasks = messages.Select(x => ProcessMessage(x, ts.Token));
Console.WriteLine("Press any key to cancel tasks")
Console.ReadKey();
ts.Cancel();
await Task.WhenAll(tasks);
Console.WriteLine("All finished");
Console.ReadKey();
}
private static async Task ProcessMessage( RealTimeMessage message, CancellationToken token )
{
try
{
while (!token.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromSeconds(60), token);
ProcessRequest(message);
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation Cancelled");
}
catch (Exception ex)
{
Console.WriteLine("Critical error: " + ex.Message);
}
}
要取消你的任务,只需调用ts.Cancel()
。
我写了一些代码,其中我使用 Parallel.Foreach 一些项目与无限循环并行工作,即每 60 秒后工作正常。
但是这里我的消息可以被用户随时更改,我需要用新消息重新处理。 为此,我需要取消无限 Parallel.Foreach 循环以重新处理更新的消息。
当我尝试重新处理 main 方法时,它对新消息工作正常,但它 运行ning 两次,因为之前的计划任务没有被取消。我假设我需要从 Parrallel.Foreach 循环中取消进程,然后重新 运行 以获取具有新计划的更新消息。
谁能帮我取消已经安排在下一个 60 秒的排队任务。
static void Main(string[] args)
{
List<RealTimeMessage> messages = GetRealTimeMessage();
Parallel.ForEach(messages, (message) =>
{
processMessage(message);
});
Console.ReadLine();
}
private static async void processMessage(RealTimeMessage message)
{
try
{
while (true)
{
await Task.Delay(TimeSpan.FromSeconds(60));
await Task.Run(() => ProceesRequest(message));
}
}
catch (Exception)
{
Console.WriteLine("Critical error");
}
}
private static List<RealTimeMessage> GetRealTimeMessage()
{
List<RealTimeMessage> realTimeMessages = new List<RealTimeMessage>();
realTimeMessages.Add(new RealTimeMessage { MessageText = "Message 4", IntervalTime = "1", MessageType = "AIDX", TimeOfDay = "" });
realTimeMessages.Add(new RealTimeMessage { MessageText = "Message 5", IntervalTime = "2", MessageType = "AMSX", TimeOfDay = "" });
return realTimeMessages;
}
private static void ProceesRequest(RealTimeMessage message)
{
// do domething
}
- 这是对
Parallel.ForEach
的误用,请改用Task.WhenAll
- 不要在 ProcessMessage 中启动
Task
(这可能是故意的,但看起来像是一个错误)。 - 使用
CancellationToken
来取消一个任务 - 不要使用
async void
除非它是为了一个事件 - 方法名称使用标准大小写
- 不要使用
while(true)
使用while (!token.IsCancellationRequested)
考虑到所有因素后,它看起来像这样
static async Task Main(string[] args)
{
var ts = new CancellationTokenSource();
var messages = GetRealTimeMessage();
var tasks = messages.Select(x => ProcessMessage(x, ts.Token));
Console.WriteLine("Press any key to cancel tasks")
Console.ReadKey();
ts.Cancel();
await Task.WhenAll(tasks);
Console.WriteLine("All finished");
Console.ReadKey();
}
private static async Task ProcessMessage( RealTimeMessage message, CancellationToken token )
{
try
{
while (!token.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromSeconds(60), token);
ProcessRequest(message);
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation Cancelled");
}
catch (Exception ex)
{
Console.WriteLine("Critical error: " + ex.Message);
}
}
要取消你的任务,只需调用ts.Cancel()
。