在我的Asp.Net MVC 5项目中,我有一个约3分钟的任务,我将其传递给Task.Factory.StartNew()。
如果在任务中运行的代码的其中一个步骤中存在验证问题,我想暂停任务中的任务。我不想将其延迟异步,因为剩下的任务将继续运行,这是不可能发生的。
我可以使用thread.sleep()而不会产生任何影响因为我在任务中吗?我读到我可能必须使用TaskScheduler.Default让Task.Factory为每个任务创建一个新线程。
我正在使用类似于CancellationToken的PauseToken,因此我将能够根据用户输入恢复任务或取消此任务。
多线程真的让我害怕,我不想忽视某些事情。
以下是Thread.Sleep实现的示例:
public void WaitIfPaused(PauseToken pauseToken, CancellationToken cancellationToken, IProgressBar progressBar)
{
//TODO: If paused for an hour notify user via noty and abort the task to keep it from completing by cancellation via cancellationToken.
//wait for 1 hour
for (int i = 0; i < 3600; i++)
{
ThrowExceptionIfCancelled(cancellationToken, progressBar);
if (pauseToken.IsPaused)
{
Thread.Sleep(1000);
}
else
{
break;
}
}
}
PauseToken:http://blogs.msdn.com/b/pfxteam/archive/2013/01/13/cooperatively-pausing-async-methods.aspx
请求:在共享代码库中实现任务结构。
public void StartTask(params object[] data)
{
//throw an exception if no ITask was found
if (_taskToRun == null)
throw new Exception("Task cannot be null");
//set up task cancellation
CancellationTokenSource = new CancellationTokenSource();
var cancellationToken = CancellationTokenSource.Token;
//set up task pausing
PauseTokenSource = new PauseTokenSource();
var pauseToken = PauseTokenSource.Token;
//start a new task using the Task that was set
_task = Task.Factory.StartNew(() => _taskToRun.Execute(cancellationToken, pauseToken, data), cancellationToken);
}
我的执行方法由_taskToRun.Execute:
调用Public override void Execute(CancellationToken cancellationToken, PauseToken pauseToken, params object[] data)
{
var managerList = (List<IFileManager>) data[0];
var instr = (List<InstructionSet>) data[1];
ProcessInstructions(managerList, instr, cancellationToken, pauseToken);
}
由于评论而更新:
代码示例:3条指令
For(var instruction in instructions)
{
instruction.Execute();
}
在我的执行方法中,我遇到暂停的场景,并在执行中调用WaitWhilePausedAsync。它将继续执行其他两条指令,但只暂停当前指令的执行方法。
编辑:等待instruction.Execute()它会等到instruction.Execute()完成或取消暂停。
最终编辑: 我能够通过等待Execute方法解决问题,并像Servy和I3arnon建议的那样使其异步。
最终代码示例:
foreach(var instruction in instructions)
{
try
{
await instruction.Execute(pauseToken);
}
catch(InvalidOperationException)
{
pauseTokenSource.IsPaused = true;
//ask if user wants to cancel or resume.
}
}
//Simplified
public async Task<bool> Execute(PauseToken pauseToken)
{
await pauseToken.WaitWhilePausedAsync();
//do work
}
答案 0 :(得分:0)
您可以安全地使用Thread.Sleep
。唯一的缺点是线程会被同步浪费阻塞。
您应该使用await Task.Delay(1000)
代替。该行之后的代码在等待完成之前不会执行,但在此期间你不会浪费一个线程:
public async Task WaitIfPausedAsync(PauseToken pauseToken, CancellationToken cancellationToken, IProgressBar progressBar)
{
for (int i = 0; i < 3600; i++)
{
ThrowExceptionIfCancelled(cancellationToken, progressBar);
if (pauseToken.IsPaused)
{
await Task.Delay(1000)
}
else
{
break;
}
}
}
编辑:我不知道PauseToken.WaitWhilePausedAsync
。您应该明确地使用它,而不是通过PauseToken.IsPaused