C#使用DataflowBlock.Completion来取消使用者任务,而不是CancellationToken
我想知道是否有一种简洁的方法来取代需要使用取消令牌的C#使用DataflowBlock.Completion来取消使用者任务,而不是CancellationToken,c#,task-parallel-library,tpl-dataflow,C#,Task Parallel Library,Tpl Dataflow,我想知道是否有一种简洁的方法来取代需要使用取消令牌的ReceiveAsyncIDataflowBlock.Completion或类似的方法,该方法使用BufferBlock或另一个IDataflowBlock IDataflowBlock.ReceiveAsync<T>(TimeSpan, CancellationToken) 如果InputQueue.Complete(),然后当队列清空且IDataflowBlock.Completion将变为状态RanToCompletion时
ReceiveAsync
IDataflowBlock.Completion或类似的方法,该方法使用BufferBlock
或另一个IDataflowBlock
IDataflowBlock.ReceiveAsync<T>(TimeSpan, CancellationToken)
如果InputQueue.Complete()调用了code>,然后当队列清空且IDataflowBlock.Completion
将变为状态RanToCompletion时,
可以使用IDataflowBlock.Completion.IsCompleted
检查
如果有多个线程从队列中执行操作,则这可能发生在InputQueue.ReceiveAsync
期间,是否有比以下更整洁的方法来处理InputQueue
完成操作:
try
{
String parcel = await InputQueue.ReceiveAsync(timeSpan);
}
catch(InvalidOperationException x)
{
}
最简单的方法是向块的构造函数提供令牌,如下所示:
new ExecutionDataflowBlockOptions
{
CancellationToken = cancellationSource.Token
});
internal void HandleMessage()
{
try
{
var parcel = await InputQueue.ReceiveAsync(timeSpan);
// handle parsel
}
catch(InvalidOperationException x)
{
}
}
var InputQueue = new BufferBlock<string>();
var Handler = new ActionBlock<string>(parcel =>
{
// handle parsel
});
var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
InputQueue.LinkTo(Handler, linkOptions);
// now after you call Complete method for InputQueue the completion will be propagated to your Handler block:
for (int i = 0; i < 26; i++)
{
await InputQueue.SendAsync(((char)(97 + i)).ToString());
}
InputQueue.Complete();
await Handler.Completion;
,因此甚至可以取消BufferBlock
为什么您要自己实现Receive
逻辑?是否存在使用“否”的限制?例如,如果您的代码如下所示:
new ExecutionDataflowBlockOptions
{
CancellationToken = cancellationSource.Token
});
internal void HandleMessage()
{
try
{
var parcel = await InputQueue.ReceiveAsync(timeSpan);
// handle parsel
}
catch(InvalidOperationException x)
{
}
}
var InputQueue = new BufferBlock<string>();
var Handler = new ActionBlock<string>(parcel =>
{
// handle parsel
});
var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
InputQueue.LinkTo(Handler, linkOptions);
// now after you call Complete method for InputQueue the completion will be propagated to your Handler block:
for (int i = 0; i < 26; i++)
{
await InputQueue.SendAsync(((char)(97 + i)).ToString());
}
InputQueue.Complete();
await Handler.Completion;
然后,您只需像这样使用ActionBlock
:
new ExecutionDataflowBlockOptions
{
CancellationToken = cancellationSource.Token
});
internal void HandleMessage()
{
try
{
var parcel = await InputQueue.ReceiveAsync(timeSpan);
// handle parsel
}
catch(InvalidOperationException x)
{
}
}
var InputQueue = new BufferBlock<string>();
var Handler = new ActionBlock<string>(parcel =>
{
// handle parsel
});
var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
InputQueue.LinkTo(Handler, linkOptions);
// now after you call Complete method for InputQueue the completion will be propagated to your Handler block:
for (int i = 0; i < 26; i++)
{
await InputQueue.SendAsync(((char)(97 + i)).ToString());
}
InputQueue.Complete();
await Handler.Completion;
var InputQueue=new BufferBlock();
变量处理程序=新动作块(地块=>
{
//句柄解析器
});
var linkOptions=newdataflowlinkoptions{PropagateCompletion=true};
LinkTo(处理程序,linkOptions);
//现在,在为InputQueue调用Complete方法后,完成操作将传播到处理程序块:
对于(int i=0;i<26;i++)
{
等待InputQueue.SendAsync(((char)(97+i)).ToString();
}
InputQueue.Complete();
等待处理者完成;
还请注意,如果您需要与UI进行一些交互,可以将最后一个块与库一起使用。最简单的方法是向块的构造函数提供令牌,如下所示:
new ExecutionDataflowBlockOptions
{
CancellationToken = cancellationSource.Token
});
internal void HandleMessage()
{
try
{
var parcel = await InputQueue.ReceiveAsync(timeSpan);
// handle parsel
}
catch(InvalidOperationException x)
{
}
}
var InputQueue = new BufferBlock<string>();
var Handler = new ActionBlock<string>(parcel =>
{
// handle parsel
});
var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
InputQueue.LinkTo(Handler, linkOptions);
// now after you call Complete method for InputQueue the completion will be propagated to your Handler block:
for (int i = 0; i < 26; i++)
{
await InputQueue.SendAsync(((char)(97 + i)).ToString());
}
InputQueue.Complete();
await Handler.Completion;
,因此甚至可以取消BufferBlock
为什么您要自己实现Receive
逻辑?是否存在使用“否”的限制?例如,如果您的代码如下所示:
new ExecutionDataflowBlockOptions
{
CancellationToken = cancellationSource.Token
});
internal void HandleMessage()
{
try
{
var parcel = await InputQueue.ReceiveAsync(timeSpan);
// handle parsel
}
catch(InvalidOperationException x)
{
}
}
var InputQueue = new BufferBlock<string>();
var Handler = new ActionBlock<string>(parcel =>
{
// handle parsel
});
var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
InputQueue.LinkTo(Handler, linkOptions);
// now after you call Complete method for InputQueue the completion will be propagated to your Handler block:
for (int i = 0; i < 26; i++)
{
await InputQueue.SendAsync(((char)(97 + i)).ToString());
}
InputQueue.Complete();
await Handler.Completion;
然后,您只需像这样使用ActionBlock
:
new ExecutionDataflowBlockOptions
{
CancellationToken = cancellationSource.Token
});
internal void HandleMessage()
{
try
{
var parcel = await InputQueue.ReceiveAsync(timeSpan);
// handle parsel
}
catch(InvalidOperationException x)
{
}
}
var InputQueue = new BufferBlock<string>();
var Handler = new ActionBlock<string>(parcel =>
{
// handle parsel
});
var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
InputQueue.LinkTo(Handler, linkOptions);
// now after you call Complete method for InputQueue the completion will be propagated to your Handler block:
for (int i = 0; i < 26; i++)
{
await InputQueue.SendAsync(((char)(97 + i)).ToString());
}
InputQueue.Complete();
await Handler.Completion;
var InputQueue=new BufferBlock();
变量处理程序=新动作块(地块=>
{
//句柄解析器
});
var linkOptions=newdataflowlinkoptions{PropagateCompletion=true};
LinkTo(处理程序,linkOptions);
//现在,在为InputQueue调用Complete方法后,完成操作将传播到处理程序块:
对于(int i=0;i<26;i++)
{
等待InputQueue.SendAsync(((char)(97+i)).ToString();
}
InputQueue.Complete();
等待处理者完成;
还请注意,如果您需要与UI进行一些交互,可以将最后一个块用作库。您的示例try catch
不是处理完成的方式。调用.Complete()
后,应等待block.Completion
。你到底想做什么?此外,除非您有特定的理由需要使用receiveasync
,否则您应该更喜欢使用LinkTo
方法创建的块之间的链接。我有一些代码,其中许多生产者任务将数据包放在缓冲块上,许多其他任务从缓冲块读取数据包,读卡器任务有一个令牌,当没有更多生产者加载队列时通知它们。鉴于该逻辑类似于isCompleted逻辑,我希望消除对令牌的需求。我将查看链接以明确查看LinkTo
,在TPL数据流中,根据您的需要,您的消费任务将成为ActionBlock
或TransformBlock
。一旦它们被链接,您只需传播完成以关闭管道。您的示例try catch
不是您处理完成的方式。调用.Complete()
后,应等待block.Completion
。你到底想做什么?此外,除非您有特定的理由需要使用receiveasync
,否则您应该更喜欢使用LinkTo
方法创建的块之间的链接。我有一些代码,其中许多生产者任务将数据包放在缓冲块上,许多其他任务从缓冲块读取数据包,读卡器任务有一个令牌,当没有更多生产者加载队列时通知它们。鉴于该逻辑类似于isCompleted逻辑,我希望消除对令牌的需求。我将查看链接以明确查看LinkTo
,在TPL数据流中,根据您的需要,您的消费任务将成为ActionBlock
或TransformBlock
。一旦它们被链接,你就可以简单地传播完成来关闭管道。好了,ActionBlock是我的答案,我让消费者直接从by buffer block中获取,将其更改为:生产者提供bufferblock,bufferblock链接到action block/s。我将试验maxDegreeOfParallelism和限制用户的有界容量OK got,ActionBlock是我的答案,我让用户直接从by buffer block中获取,将其更改为:生产者提供bufferblock,bufferblock链接到action block/s。我将用maxDegreeOfParallelism和有界容量来限制用户