我已根据我在此处找到的内容实现了工作队列> Task queue for wp8? ...但是无法使用它实现其他功能。
我取出了Func<Task>
并将其替换为ICommands(持有自己的CancellationTokens),并打算添加Pause()
,Resume()
,Save()
&amp; ; Restore()
方法。这是OnFormClose()
我可以暂停队列处理并提示用户决定是否“等待队列完成”(即恢复),或“立即退出”(即保存并退出)。 / p>
public class WqController
{
private readonly Queue<ICommand> _queue = new Queue<ICommand>();
private Task _queueProcessor;
private ICommand _curCommand;
public void Enqueue(ICommand command)
{
_queue.Enqueue(command);
if (_queueProcessor == null) _queueProcessor = ProcessQueue();
}
private async Task ProcessQueue()
{
try
{
while (_queue.Count != 0)
{
_curCommand = _queue.Peek();
try
{
await Task.Run(() => _curCommand.Execute());
}
catch (OperationCanceledException)
{
Console.WriteLine("QUEUE PAUSED");
return;
}
catch (Exception)
{
Console.WriteLine("FAILED TO EXECUTE COMMAND");
}
_queue.Dequeue();
}
}
finally
{
_queueProcessor = null;
_curCommand = null;
}
}
public async Task Cancel()
{
_curCommand.Cts.Cancel(true);
await _queueProcessor;
}
public void Resume()
{
_queueProcessor = ProcessQueue();
}
}
Save()
&amp; Restore()
工作正常,所以我没有把它们包含在这里。 Cancel()
间歇地/不可靠地工作,而Restore()
似乎根本不起作用(令我感到困惑,因为我基本上尝试了与Enqueue()
中的工作相同的重启法)。
答案 0 :(得分:0)
我得到了这个工作,并认为我应该在这里概述我的解决方案。
事实证明,我对取消令牌的使用有点偶然,这阻止了这个类按预期运行。例如,以下问题是相关的:
如果在命令中通过了最后一次取消检查后调用了Cancel,则会加载一个新命令(以及它自己的新取消令牌),因此取消调用将被丢失/忽略。这是在if (_curCommand.Cts.Token.IsCancellationRequested) return;
之后_queue.Dequeue();
解决的。
在调用取消后,如果稍后要恢复该命令,那么它将需要一个新的取消令牌(否则具有cancel = true的现有命令仍将处于活动状态)。行_curCommand.InvalidateCancellationToken();
通过将令牌设置为null来执行此操作,然后我的命令在下次调用时刷新令牌。
我使用的完整代码:
public class WqController
{
private readonly Queue<ICommand> _queue = new Queue<ICommand>();
private Task _queueProcessor;
private ICommand _curCommand;
public void Enqueue(ICommand command)
{
_queue.Enqueue(command);
if (_queueProcessor == null) _queueProcessor = ProcessQueue();
}
private async Task ProcessQueue()
{
try
{
while (_queue.Count != 0)
{
_curCommand = _queue.Peek();
try
{
await Task.Run(() => _curCommand.Execute());
}
catch (OperationCanceledException)
{
_curCommand.InvalidateCancellationToken();
Console.WriteLine("QUEUE PAUSED");
return;
}
catch (Exception)
{
Console.WriteLine("FAILED TO EXECUTE COMMAND");
}
_queue.Dequeue();
if (_curCommand.Cts.Token.IsCancellationRequested) return;
}
}
finally
{
_queueProcessor = null;
_curCommand = null;
}
}
public async Task Cancel()
{
_curCommand.Cts.Cancel(true);
await _queueProcessor;
}
public void Resume()
{
_queueProcessor = ProcessQueue();
}
}
这一切似乎现在都非常顺利,并且是我之前使用的后台工作队列实现的一个重大改进。