当我取消任务时,等待结果仍然为IsCanceled属性返回true.似乎有些事情出了问题.
请指教.这是代码:
CancellationTokenSource _cancelLationToken = new CancellationTokenSource();
private async void Button_Click(object sender, EventArgs e)
{
_cancelLationToken = new CancellationTokenSource();
_cancelLationToken.Token.Register(theCallBack);
var myTaskToWaitFor = Task.Factory.StartNew(() => WorkHard(_cancelLationToken.Token), _cancelLationToken.Token);
await myTaskToWaitFor;
int i=0;
if(myTaskToWaitFor.IsCanceled)
i = i; //breakpoint for debugging
else
i = i; //breakpoint for debugging <== always ends here... :-(
}
private void WorkHard(CancellationToken token)
{
for(int i = 0; i < 100000000; i++)
if(token.IsCancellationRequested)
break;
else
Math.Acos(Math.Pow(i, i / 10000000));
}
public void theCallBack()
{
//todo: do something
} …Run Code Online (Sandbox Code Playgroud) 我需要做的是能够取消运行异步的任务.
我一直在寻找,似乎无法绕过它.我似乎无法辨别它将如何实现到我当前的设置中.
这是我的代码,它解雇了我的任务.任何有关在何处或如何实施取消令牌的帮助将不胜感激.
private async void startThread()
{
//do ui stuff before starting
ProgressLabel.Text = String.Format("0 / {0} Runs Completed", index.Count());
ProgressBar.Maximum = index.Count();
await ExecuteProcesses();
//sort list of output lines
outputList = outputList.OrderBy(o => o.RunNumber).ToList();
foreach (Output o in outputList)
{
string outStr = o.RunNumber + "," + o.Index;
foreach (double oV in o.Values)
{
outStr += String.Format(",{0}", oV);
}
outputStrings.Add(outStr);
}
string[] csvOut = outputStrings.ToArray();
File.WriteAllLines(settings.OutputFile, csvOut);
//do ui stuff after completing.
ProgressLabel.Text = index.Count() + " runs …Run Code Online (Sandbox Code Playgroud) 我在任务取消模式上发现了一个问题,我想了解为什么应该以这种方式工作。
考虑这个小程序,其中辅助线程执行异步“长”任务。同时,主线程通知取消。
该程序是一个较大的程序的非常简化的版本,可以有许多并发线程来执行“长任务”。当用户要求取消时,应取消所有正在运行的任务,因此取消了CancellationTokenSource集合。
class Program
{
static MyClass c = new MyClass();
static void Main(string[] args)
{
Console.WriteLine("program=" + Thread.CurrentThread.ManagedThreadId);
var t = new Thread(Worker);
t.Start();
Thread.Sleep(500);
c.Abort();
Console.WriteLine("Press any key...");
Console.ReadKey();
}
static void Worker()
{
Console.WriteLine("begin worker=" + Thread.CurrentThread.ManagedThreadId);
try
{
bool result = c.Invoker().Result;
Console.WriteLine("end worker=" + result);
}
catch (AggregateException)
{
Console.WriteLine("canceled=" + Thread.CurrentThread.ManagedThreadId);
}
}
class MyClass
{
private List<CancellationTokenSource> collection = new List<CancellationTokenSource>();
public async Task<bool> Invoker()
{
Console.WriteLine("begin invoker=" + Thread.CurrentThread.ManagedThreadId);
var cts …Run Code Online (Sandbox Code Playgroud) 好的,所以我了解如何使用CancellationTokenSource. 在我看来,“Task种类”类型会自动处理此异常 - 它将Task's 设置Status为 Cancelled。
现在您实际上仍然需要处理OperationCancelledException. 否则异常冒泡到Application.UnhandledException. Task 本身可以识别它并在内部进行一些处理,但您仍然需要将调用代码包装在 try 块中以避免未处理的异常。有时,这似乎是不必要的代码。如果用户按下取消,则取消Task(显然任务本身也需要处理它)。我觉得不需要任何其他代码要求。只需检查Status任务完成状态的属性。
从语言设计的角度来看,这有什么具体原因吗?有没有其他方法可以将Status属性设置为取消?
.net c# task-parallel-library cancellation cancellationtokensource
什么是确保只有'last-in'线程被授予访问互斥锁/锁定区域的正确方法,而中间线程不获取锁?
示例顺序:
A acquires lock
B waits
C waits
B fails to acquire lock*
A releases lock
C acquires lock
Run Code Online (Sandbox Code Playgroud)
*B应该无法通过异常(如in SemaphoreSlim.Wait(CancellationToken)或boolean Monitor.TryEnter()类型构造)获取锁.
我可以想到几个类似的方案来实现这一点(例如使用CancellationTokenSource和SemaphoreSlim),但它们中没有一个看起来特别优雅.
这种情况有通用的做法吗?
我有一个计时器,每 2 秒启动 2 个任务...我在一个简单的列表中跟踪这些任务(这样我可以在停止应用程序时等待它们完成)。
这些任务有效地进入数据库,运行一些更新并完成。
任务本身的运行时间不会超过一秒
...
// global variables to keep track of the running tasks.
List<Task> _tasks = new List<Task>();
CancellationTokenSource _cts = new CancellationTokenSource();
// in the timer function
private void Timer(object sender, ElapsedEventArgs e)
{
_tasks.Add( Foo1Async(_cts.Token) );
_tasks.Add( Foo2Async(_cts.Token) );
// remove the completed ones
_tasks.RemoveAll(t => t.IsCompleted);
}
...
Run Code Online (Sandbox Code Playgroud)
几分钟后,内存从 40Mb 增加到 130Mb,(并且还在攀升)...
如果我只替换下面的代码而不替换其他任何内容
...
_tasks.Add( Foo1Async( CancellationToken.None)) );
_tasks.Add( Foo2Async( CancellationToken.None)) );
...
Run Code Online (Sandbox Code Playgroud)
内存保持稳定在 40Mb,永远不会增加。
有几点
当我们的应用程序正在从数据库或 http 请求中读取一些数据并且用户点击取消按钮时,我希望能够立即取消从数据库或 http 请求中读取。这两个调用都不能立即取消,即使对于调用的异步版本也是如此。
如果我将代码设置为在下一个数据库/http 调用完成后立即结束任务怎么办?然后忘记那个任务并继续在我的应用程序中?我可以看到的一个缺点是如果在用户存在应用程序之前任务没有完成。
更新: JPVenson 为 http 和 ADO.NET 提供了一个很好的解决方案。但是,我们有时也会调用 Salesforce API,据我所知,它没有取消机制。所以这个问题仍然存在。
在取消时,我不需要返回的内容,因此从我的应用程序的角度来看,我可以忘记任务。这样做有什么缺点吗?
我正在使用TPL块来执行可能被用户取消的操作:我提出了两个选项,首先我取消整个块但不取消块内的操作,如下所示:
_downloadCts = new CancellationTokenSource();
var processBlockV1 = new TransformBlock<int, List<int>>(construct =>
{
List<int> properties = GetPropertiesMethod(construct );
var entities = properties
.AsParallel()
.Select(DoSometheningWithData)
.ToList();
return entities;
}, new ExecutionDataflowBlockOptions() { CancellationToken = _downloadCts.Token });
Run Code Online (Sandbox Code Playgroud)
第二个我取消内部操作,但不是块本身:
var processBlockV2 = new TransformBlock<int, List<int>>(construct =>
{
List<int> properties = GetPropertiesMethod(construct);
var entities = properties
.AsParallel().WithCancellation(_downloadCts.Token)
.Select(DoSometheningWithData)
.ToList();
return entities;
});
Run Code Online (Sandbox Code Playgroud)
据我了解,第一个选项将取消整个块,从而关闭整个管道。我的问题是它是否也会取消内部操作并处理所有资源(如果有)(打开 StreamReaders 等),或者最好选择第二个选项,然后我自己可以确保所有内容都被取消和清理,然后我可以使用一些方法(铁路编程)漂浮OperationCanceledException在管道上并在我想要的地方处理它?
c# task-parallel-library cancellationtokensource tpl-dataflow
当我取消从浏览器到 HTTP 触发器的请求时,它不会取消,而是在 Azure 上托管时继续执行。
我的函数示例:
[FunctionName("Test")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
CancellationToken cancellationToken,
ILogger log)
{
var allCancellationTokens = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, req.HttpContext.RequestAborted);
await Task.Delay(30000, allCancellationTokens.Token);
if (allCancellationTokens.IsCancellationRequested) {
log.LogInformation("Request was cancelled!");
return new StatusCodeResult(499);
}
return new OkObjectResult("Complete");
}
Run Code Online (Sandbox Code Playgroud)
我一直在通过 Postman 和 axios 取消令牌测试取消。当我在本地运行项目并取消它时,它可以工作,但一旦发布到天蓝色,它似乎就不会取消。
我的预期结果是,OperationCanceledException如果我在执行期间取消请求,它会抛出await Task.Delay(30000, allCancellationTokens.Token);异常。但是,在检查 Azure Functions 上的日志时,似乎只是继续执行并完成该函数。
重现步骤:
c# azure cancellationtokensource cancellation-token azure-functions
我开发了一个基于 C# 的 Windows 服务,它在几个不同的任务中运行其所有逻辑。为了允许服务在停止时正常关闭,我使用 CancellationToken ,它被传递给任何接受一个的函数(主要来自我正在使用的第三方库),以便在完成之前中止处理。
我注意到,OperationCanceledException当调用函数时请求取消时,这些函数都不会抛出异常,因此我的应用程序只是继续执行,直到我ThrowIfCancellationRequested()稍后在代码中调用其他地方。我是否应该ThrowIfCancellationRequested()在调用每个函数后手动调用以确保任务尽快停止,或者我到底应该何时调用ThrowIfCancellationRequested()自己的代码?
c# multithreading synchronization cancellationtokensource cancellation-token
c# ×9
.net ×2
async-await ×2
task ×2
asynchronous ×1
azure ×1
cancellation ×1
locking ×1
mutex ×1
tpl-dataflow ×1