考虑下面的摘录。
表单将 BusyForm 添加到队列中,稍后,当表单完成时,它会设置TCS的结果,将其标记为完成,而不从队列中删除该项目。
过了一会儿,有些事情发生了,我们需要等待所有繁忙的表单,所以我们等待每个TCS任务
在队列中。但惊讶,惊讶.. GC抓住了它。
为什么呢?它不是由队列引用的吗?
static class Global
{
public static ConcurrentQueue<BusyForm> BusyForms = new ConcurrentQueue<BusyForm>();
public class BusyForm
{
public string Name;
public TaskCompletionSource<bool> Done = new TaskCompletionSource<bool>();
public BusyForm(string name)
{
this.Name = name;
}
}
}
// somewhere else when form is done
busyForm.Done.SetResult(true);
// after a while, when required
while(!Global.BusyForms.IsEmpty)
{
Global.BusyForms.TryPeek(out busyForm);
await busyForm.Done.Task; // can be disposed by GC if finished a long time ago
Global.BusyForms.TryDequeue(out busyForm);
}
答案 0 :(得分:1)
目前尚不清楚这一切是如何组合在一起的,但似乎你的过程应该只是:
while(!Global.BusyForms.IsEmpty)
{
if(Global.BusyForms.TryDequeue(out busyForm))
await busyForm.Done.Task; // can be disposed by GC if finished a long time ago
else
{
// could not dequeue for some reason - need to break the loop so that we no not get in an infinite loop.
break;
// or perhaps throw an exception?
}
}
这样就不会有同样Task
被处理两次的风险。当一个项目仍然在队列中时处理它似乎很奇怪。考虑在机场办理登机手续 - 在排队时不办理登机手续 - 您将被拉出线路,以便下一个可用的代理人服务。