某些System.Threading.Tasks.Task
构造函数将a CancellationToken
作为参数:
CancellationTokenSource source = new CancellationTokenSource();
Task t = new Task (/* method */, source.Token);
Run Code Online (Sandbox Code Playgroud)
令我感到困惑的是,从方法体内部无法实际获取传入的令牌(例如,没有什么比这样Task.CurrentTask.CancellationToken
).必须通过某种其他机制提供令牌,例如状态对象或在lambda中捕获.
那么在构造函数中提供取消令牌的目的是什么呢?
我正在寻找除了CancellationTokenSource类之外还引入.NET CancellationToken结构的原因.我的理解是如何的API被使用,但想也明白为什么它就是这样设计的.
即,我们为什么要:
var cts = new CancellationTokenSource();
SomeCancellableOperation(cts.Token);
...
public void SomeCancellableOperation(CancellationToken token) {
...
token.ThrowIfCancellationRequested();
...
}
Run Code Online (Sandbox Code Playgroud)
而不是直接传递CancellationTokenSource,如:
var cts = new CancellationTokenSource();
SomeCancellableOperation(cts);
...
public void SomeCancellableOperation(CancellationTokenSource cts) {
...
cts.ThrowIfCancellationRequested();
...
}
Run Code Online (Sandbox Code Playgroud)
这是一个基于以下事实的性能优化:取消状态检查比传递令牌更频繁吗?
因此CancellationTokenSource可以跟踪和更新CancellationTokens,并且对于每个令牌,取消检查是本地字段访问?
鉴于两种情况下没有锁定的挥发性bool就足够了,我仍然无法理解为什么会更快.
谢谢!
.net multithreading task-parallel-library cancellationtokensource cancellation-token
我有一些异步代码,我想添加一个CancellationToken.但是,有许多实现不需要这样做,所以我想有一个默认参数 - 也许是CancellationToken.None.然而,
Task<x> DoStuff(...., CancellationToken ct = null)
Run Code Online (Sandbox Code Playgroud)
产量
类型''的值不能用作默认参数,因为没有标准转换来键入'System.Threading.CancellationToken'
和
Task<x> DoStuff(...., CancellationToken ct = CancellationToken.None)
Run Code Online (Sandbox Code Playgroud)
'ct'的默认参数值必须是编译时常量
有没有办法让CancellationToken有一个默认值?
我目前正在改进我们长期运行的方法,以便取消.我打算使用System.Threading.Tasks.CancellationToken来实现它.
我们的方法通常执行一些长时间运行的步骤(主要向硬件发送命令然后等待硬件),例如
void Run()
{
Step1();
Step2();
Step3();
}
Run Code Online (Sandbox Code Playgroud)
我对取消的第一个(也许是愚蠢的)想法会将其转化为
bool Run(CancellationToken cancellationToken)
{
Step1(cancellationToken);
if (cancellationToken.IsCancellationRequested)
return false;
Step2(cancellationToken);
if (cancellationToken.IsCancellationRequested)
return false;
Step3(cancellationToken);
if (cancellationToken.IsCancellationRequested)
return false;
return true;
}
Run Code Online (Sandbox Code Playgroud)
坦率地看起来很可怕.这种"模式"也将在单个步骤内继续(并且它们必然已经相当长).这会使Thread.Abort()看起来很性感,虽然我知道它不推荐.
有没有更清晰的模式来实现这一点,不会隐藏许多样板代码下面的应用程序逻辑?
编辑
作为步骤性质的一个例子,该Run
方法可以阅读
void Run()
{
GiantRobotor.MoveToBase();
Oven.ThrowBaguetteTowardsBase();
GiantRobotor.CatchBaguette();
// ...
}
Run Code Online (Sandbox Code Playgroud)
我们正在控制需要同步的不同硬件单元才能协同工作.
async ctp
今天早上我一直在玩,并有一个简单的程序与a button
和a label
.点击button
它开始更新label
,停止button
它停止写入label
.但是,我不确定如何重置,CancellationTokenSource
以便我可以重新启动该过程.我的代码如下:
public partial class MainWindow : Window
{
CancellationTokenSource cts = new CancellationTokenSource();
public MainWindow()
{
InitializeComponent();
button.Content = "Start";
}
async Task DoWork(CancellationToken cancelToken)
{
int i = 0;
while (!cancelToken.IsCancellationRequested)
{
label.Content = i++.ToString();
await TaskEx.Delay(50, cancelToken);
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (button.Content == "Start")
{
button.Content = "Stop";
DoWork(cts.Token);
}
else
{
button.Content = "Start";
cts.Cancel(); …
Run Code Online (Sandbox Code Playgroud) c# asynchronous async-await cancellationtokensource cancellation-token
异步控制器有不同的示例.其中一些在方法定义中使用CancellationToken:
public async Task<ActionResult> ShowItem(int id, CancellationToken cancellationToken)
{
await Database.GetItem(id, cancellationToken);
...
Run Code Online (Sandbox Code Playgroud)
但是其他示例甚至是VS2013的默认ASP.NET项目根本不使用CancellationToken而没有使用它:
public async Task<ActionResult> ShowItem(int id)
{
await Database.GetItem(id);
...
Run Code Online (Sandbox Code Playgroud)
目前尚不清楚,我们是否应该在控制器中使用CancellationToken(以及为什么).
c# asp.net-mvc async-await asp.net-web-api cancellation-token
好的,我的问题非常简单.为什么这段代码不会抛出TaskCancelledException
?
static void Main()
{
var v = Task.Run(() =>
{
Thread.Sleep(1000);
return 10;
}, new CancellationTokenSource(500).Token).Result;
Console.WriteLine(v); // this outputs 10 - instead of throwing error.
Console.Read();
}
Run Code Online (Sandbox Code Playgroud)
但这一个有效
static void Main()
{
var v = Task.Run(() =>
{
Thread.Sleep(1000);
return 10;
}, new CancellationToken(true).Token).Result;
Console.WriteLine(v); // this one throws
Console.Read();
}
Run Code Online (Sandbox Code Playgroud) .net c# task-parallel-library cancellationtokensource cancellation-token
我使用传递的取消令牌,以便可以干净地关闭我的服务.该服务具有不断尝试连接到其他服务的逻辑,因此令牌是打破在单独线程中运行的这些重试循环的好方法.我的问题是我需要调用一个具有内部重试逻辑的服务,但是如果重试失败则在一段时间后返回.我想创建一个带有超时的新取消令牌,这将为我做到这一点.这个问题是我的新令牌没有链接到"主"令牌,所以当主令牌被取消时,我的新令牌仍然有效,直到它超时或建立连接并返回.我想要做的是将两个令牌链接在一起,这样当主要的一个被取消时,我的新一个也会取消.我尝试使用该CancellationTokenSource.CreateLinkedTokenSource
方法但是当我的新令牌超时时,它也取消了主令牌.有没有办法做我需要做的令牌,或者它需要更改重试逻辑(可能不会轻易做到这一点)
这是我想要做的:
主令牌 - 传递各种功能,以便服务可以干净地关闭.临时令牌 - 传递给单个函数并在一分钟后设置为超时
如果取消主令牌,则还必须取消临时令牌.
当临时令牌到期时,它不得取消主令牌.
这里的证明.
知道这段代码有什么问题吗?
[TestMethod]
public void TestTest()
{
var tcp = new TcpClient() { ReceiveTimeout = 5000, SendTimeout = 20000 };
tcp.Connect(IPAddress.Parse("176.31.100.115"), 25);
bool ok = Read(tcp.GetStream()).Wait(30000);
Assert.IsTrue(ok);
}
async Task Read(NetworkStream stream)
{
using (var cancellationTokenSource = new CancellationTokenSource(5000))
{
int receivedCount;
try
{
var buffer = new byte[1000];
receivedCount = await stream.ReadAsync(buffer, 0, 1000, cancellationTokenSource.Token);
}
catch (TimeoutException e)
{
receivedCount = -1;
}
}
}
Run Code Online (Sandbox Code Playgroud) 看看CancellationToken.None
它的实现,它只是回归default(CancellationToken)
.但是,我在CancellationToken
文档中看不到两者是等价的.
我想提供这样的API,但直到我确定它总能工作:
Task DoSomething(CancellationToken token = default(CancellationToken))
Run Code Online (Sandbox Code Playgroud)
它定义的行为default(CancellationToken)
是否相同CancellationToken.None
,或者这只是一个实现细节?
c# ×7
.net ×5
async-await ×3
asynchronous ×2
.net-4.0 ×1
.net-4.5 ×1
ado.net ×1
asp.net-mvc ×1
linq ×1
sockets ×1