C# 这对异步生成的状态机中的MoveNext有意义吗
最近,我在读Eduasync serial。当我阅读时,有一个问题阻碍了我,我认为C生成的状态机在某些罕见的情况下可能无法正常工作,让我们深入了解代码(此代码来自Jon Skeet的Eduancy第7部分,我只是添加了一些建议):C# 这对异步生成的状态机中的MoveNext有意义吗,c#,.net,asynchronous,async-await,c#-5.0,C#,.net,Asynchronous,Async Await,C# 5.0,最近,我在读Eduasync serial。当我阅读时,有一个问题阻碍了我,我认为C生成的状态机在某些罕见的情况下可能无法正常工作,让我们深入了解代码(此代码来自Jon Skeet的Eduancy第7部分,我只是添加了一些建议): public void MoveNext() { int结果; 尝试 {//doFinallyBodies从不使用 bool doFinallyBodies=true; 如果(状态!=1) { 如果(状态!=-1) { task=task.Factory.Sta
public void MoveNext()
{
int结果;
尝试
{//doFinallyBodies从不使用
bool doFinallyBodies=true;
如果(状态!=1)
{
如果(状态!=-1)
{
task=task.Factory.StartNew(()=>5);
waiter=task.getwaiter();
//在极少数情况下,此时任务仍未完成,
//所以返回false就完成了
如果(等待者完成)
{
转到标签获取结果;
}
状态=1;
//在未完成之前刚刚完成的任务,
//但在这一刻,我们还没有宣布未完成,
//因此,任务的连续性意味着任务将无法完成
//如果没有ContinueWith,我们就再也不会回到这个状态机了。
doFinallyBodies=false;
等待者。未完成(移动下一步删除);
}
返回;
}
状态=0;
标签\u获取结果:
int waitresult=waiter.GetResult();
等待者=新任务等待者();
结果=等待结果;
}
捕获(例外e)
{
状态=-1;
builder.SetException(e);
返回;
}
状态=-1;
builder.SetResult(result);
}
公共结构任务等待器
{
私有只读任务;
内部任务等待者(任务)
{
this.task=任务;
}
public bool IsCompleted{get{return task.IsCompleted;}
未完成公共作废(行动)
{
SynchronizationContext=SynchronizationContext.Current;
TaskScheduler=context==null?TaskScheduler.Current
:TaskScheduler.FromCurrentSynchronizationContext();
task.ContinueWith(忽略=>action(),调度程序);
}
公共T GetResult()
{
返回任务。结果;
}
}
那么你认为这可能是个问题吗?为了确保我正确理解你,我将更详细地描述我认为你期待的事件顺序:
IsCompleted
,这将返回false
,因为操作尚未完成OnCompleted()
,这又调用了ContinueWith()
,但是由于任务已经完成,所以continuation永远不会执行
任务
的作者知道这种竞争条件,因此,如果您对已完成的任务
调用ContinueWith()
,将立即安排继续。因此,即使在这种情况下,状态机也能正常工作
不幸的是,我对此不是很清楚(它解释了什么时候不安排继续,但不是什么时候安排)。是的,这正是我想问的。谢谢你的回答,这对我来说很有意义。顺便问一下,除了MSDN文档外,您能否提供有关ContinueWith()的更多信息“将立即安排”。这仅仅意味着
任务将添加到当前任务计划程序中。然后由调度程序决定何时执行。这就是你要问的吗?
public void MoveNext()
{
int result;
try
{ // doFinallyBodies is never used
bool doFinallyBodies = true;
if (state != 1)
{
if (state != -1)
{
task = Task<int>.Factory.StartNew(() => 5);
awaiter = task.GetAwaiter();
// In a rare case, in this moment the task still has not completed,
// so return false IsCompleted
if (awaiter.IsCompleted)
{
goto Label_GetResult;
}
state = 1;
// The task just completed before OnCompleted,
// but in this moment we haven't call the OnCompleted yet,
// so the task's ContinueWith is nothing the task will complete
// without ContinueWith and we will never get back to this StateMachine again.
doFinallyBodies = false;
awaiter.OnCompleted(moveNextDelegate);
}
return;
}
state = 0;
Label_GetResult:
int awaitResult = awaiter.GetResult();
awaiter = new TaskAwaiter<int>();
result = awaitResult;
}
catch (Exception e)
{
state = -1;
builder.SetException(e);
return;
}
state = -1;
builder.SetResult(result);
}
public struct TaskAwaiter<T>
{
private readonly Task<T> task;
internal TaskAwaiter(Task<T> task)
{
this.task = task;
}
public bool IsCompleted { get { return task.IsCompleted; } }
public void OnCompleted(Action action)
{
SynchronizationContext context = SynchronizationContext.Current;
TaskScheduler scheduler = context == null ? TaskScheduler.Current
: TaskScheduler.FromCurrentSynchronizationContext();
task.ContinueWith(ignored => action(), scheduler);
}
public T GetResult()
{
return task.Result;
}
}