我有一个任务,我希望它能在一秒钟内运行,但是如果需要的时间超过几秒钟,我想取消任务.
例如:
Task t = new Task(() =>
{
while (true)
{
Thread.Sleep(500);
}
});
t.Start();
t.Wait(3000);
Run Code Online (Sandbox Code Playgroud)
请注意,等待3000毫秒后,等待到期.超时到期或任务是否仍在运行时,任务是否被取消?
我对如何使用条件Continuations的任务感到困惑.
如果我有一个任务,然后我想继续处理成功和错误的任务,然后等待那些完成.
void FunctionThrows() {throw new Exception("faulted");}
static void MyTest()
{
var taskThrows = Task.Factory.StartNew(() => FunctionThrows());
var onSuccess = taskThrows.ContinueWith(
prev => Console.WriteLine("success"),
TaskContinuationOptions.OnlyOnRanToCompleted);
var onError = taskThrows.ContinueWith(
prev => Console.WriteLine(prev.Exception),
TaskContinuationOptions.OnlyOnFaulted);
//so far, so good
//this throws because onSuccess was cancelled before it was started
Task.WaitAll(onSuccess, onError);
}
Run Code Online (Sandbox Code Playgroud)
这是执行任务成功/失败分支的首选方式吗?另外,我应该如何加入所有这些任务,假设我已经创建了一长串的延续,每个延续都有自己的错误处理.
//for example
var task1 = Task.Factory.StartNew(() => ...)
var task1Error = task1.ContinueWith( //on faulted
var task2 = task1.ContinueWith( //on success
var task2Error = task2.ContinueWith( //on faulted
var task3 = …Run Code Online (Sandbox Code Playgroud) 当我需要能够取消大型/长期运行工作负载的任务时,我经常使用与此类似的模板执行任务:
public void DoWork(CancellationToken cancelToken)
{
try
{
//do work
cancelToken.ThrowIfCancellationRequested();
//more work
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
Log.Exception(ex);
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
不应将OperationCanceledException记录为错误,但如果任务要转换为已取消状态,则不得吞下OperationCanceledException.除了此方法的范围之外,不需要处理任何其他异常.
这总觉得有点笨重,默认情况下visual studio会在OperationCanceledException的中断(虽然因为我使用了这种模式,我已经'关闭了User-unhandled'现在关闭了OperationCanceledException).
理想情况下,我认为我希望能够做到这样的事情:
public void DoWork(CancellationToken cancelToken)
{
try
{
//do work
cancelToken.ThrowIfCancellationRequested();
//more work
}
catch (Exception ex) exclude (OperationCanceledException)
{
Log.Exception(ex);
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
即将某种排除列表应用于捕获但没有当前不可能的语言支持(@ eric-lippert:c#vNext feature :)).
另一种方式是通过延续:
public void StartWork()
{
Task.Factory.StartNew(() => DoWork(cancellationSource.Token), cancellationSource.Token)
.ContinueWith(t => Log.Exception(t.Exception.InnerException), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
}
public void DoWork(CancellationToken cancelToken)
{
//do …Run Code Online (Sandbox Code Playgroud) 什么是AutoResetEvent的异步(等待)等价物?
如果在经典线程同步中我们会使用这样的东西:
AutoResetEvent signal = new AutoResetEvent(false);
void Thread1Proc()
{
//do some stuff
//..
//..
signal.WaitOne(); //wait for an outer thread to signal we are good to continue
//do some more stuff
//..
//..
}
void Thread2Proc()
{
//do some stuff
//..
//..
signal.Set(); //signal the other thread it's good to go
//do some more stuff
//..
//..
}
Run Code Online (Sandbox Code Playgroud)
我希望以新的异步方式做事,这样的事情会变成:
SomeAsyncAutoResetEvent asyncSignal = new SomeAsyncAutoResetEvent();
async void Task1Proc()
{
//do some stuff
//..
//..
await asyncSignal.WaitOne(); //wait for an outer …Run Code Online (Sandbox Code Playgroud) 如果任何正在运行的任务抛出异常,我想让Task.WaitAll()爆发,这样我就不必等待60秒才能完成.我该如何实现这种行为?如果WaitAll()无法实现,那么还有其他c#功能或解决方法吗?
Task task1 = Task.Run(() => throw new InvalidOperationException());
Task task2 = ...
...
try
{
Task.WaitAll(new Task[]{task1, task2, ...}, TimeSpan.FromSeconds(60));
}
catch (AggregateException)
{
// If any exception thrown on any of the tasks, break out immediately instead of wait all the way to 60 seconds.
}
Run Code Online (Sandbox Code Playgroud) 我从这里理解,任务执行顺序Task.Whenall不是确定性的,但我找不到任何有关结果顺序的信息.
结果集合是否按照输入中排序的任务或结果的顺序包含结果?
从我做的测试来看,它似乎保留了订单,但我需要确认.
c# parallel-processing concurrency asynchronous task-parallel-library
我很想知道这一点,但从未真正找到答案.
我知道这是任务调度程序的一个提示,任务调度程序将在其中运行,并且任务调度程序可以(或现在将?)决定为该任务实例化非线程池线程.
我不知道(并且令人惊讶地在互联网上找不到)是一个"经验法则"何时指定一个长期运行的任务.是一秒多长?30秒?一分钟?5分钟?它是否与应用程序使用的任务量有关系?作为程序员,我应该使用线程池中的#threads进行一些计算,我创建了多少个任务,同时长时间运行了多少个任务,并根据这个来决定是否使用长时间运行的任务?
希望在这里学点东西.
我使用以下代码
var processed = new List<Guid>();
Parallel.ForEach(items, item =>
{
processed.Add(SomeProcessingFunc(item));
});
Run Code Online (Sandbox Code Playgroud)
上面的代码线程是否安全?处理后的列表是否有可能被破坏?或者我应该在添加之前使用锁?
var processed = new List<Guid>();
Parallel.ForEach(items, item =>
{
lock(items.SyncRoot)
processed.Add(SomeProcessingFunc(item));
});
Run Code Online (Sandbox Code Playgroud)
谢谢.
考虑在没有等待的情况下使用async.
想想也许你误解了异步的作用.警告是完全正确的:如果您将方法标记为异步但不在任何地方使用等待,那么您的方法将不是异步的.如果调用它,方法中的所有代码将同步执行.
我想编写一个应该运行异步但不需要使用await的方法.例如,当使用线程时
public async Task PushCallAsync(CallNotificationInfo callNotificationInfo)
{
Logger.LogInfo("Pushing new call {0} with {1} id".Fill(callNotificationInfo.CallerId,
}
Run Code Online (Sandbox Code Playgroud)
我想要调用PushCallAsync并运行异步,不想使用等待.
我可以在C#中使用async而无需等待吗?
我想等待手动重置事件,超时并观察取消.我想出了类似下面的东西.手动重置事件对象由我无法控制的API提供.有没有办法在不接受和阻止ThreadPool线程的情况下实现这一点?
static Task<bool> TaskFromWaitHandle(WaitHandle mre, int timeout, CancellationToken ct)
{
return Task.Run(() =>
{
bool s = WaitHandle.WaitAny(new WaitHandle[] { mre, ct.WaitHandle }, timeout) == 0;
ct.ThrowIfCancellationRequested();
return s;
}, ct);
}
// ...
if (await TaskFromWaitHandle(manualResetEvent, 1000, cts.Token))
{
// true if event was set
}
else
{
// false if timed out, exception if cancelled
}
Run Code Online (Sandbox Code Playgroud)
将帖子显然,这是有道理的使用RegisterWaitForSingleObject.我试试看.
c# ×10
.net ×3
async-await ×3
task ×3
asynchronous ×2
.net-4.0 ×1
c#-4.0 ×1
c#-5.0 ×1
concurrency ×1
list ×1