如果我不关心任务完成的顺序,只需要完成它们,我还应该使用await Task.WhenAll而不是多个await吗?例如,DoWork2低于优选的方法DoWork1(以及为什么?):
using System;
using System.Threading.Tasks;
namespace ConsoleApp
{
class Program
{
static async Task<string> DoTaskAsync(string name, int timeout)
{
var start = DateTime.Now;
Console.WriteLine("Enter {0}, {1}", name, timeout);
await Task.Delay(timeout);
Console.WriteLine("Exit {0}, {1}", name, (DateTime.Now - start).TotalMilliseconds);
return name;
}
static async Task DoWork1()
{
var t1 = DoTaskAsync("t1.1", 3000);
var t2 = DoTaskAsync("t1.2", 2000);
var t3 = DoTaskAsync("t1.3", 1000);
await t1; await t2; await t3;
Console.WriteLine("DoWork1 results: {0}", String.Join(", ", …Run Code Online (Sandbox Code Playgroud) .net c# parallel-processing task-parallel-library async-await
我知道使用fire-and-forget async void方法来启动任务通常被认为是一个坏主意,因为没有跟踪任务的跟踪,处理可能在这种方法中抛出的异常是很棘手的.
我一般应该避免使用async void事件处理程序吗?例如,
private async void Form_Load(object sender, System.EventArgs e)
{
await Task.Delay(2000); // do async work
// ...
}
Run Code Online (Sandbox Code Playgroud)
我可以像这样重写它:
Task onFormLoadTask = null; // track the task, can implement cancellation
private void Form_Load(object sender, System.EventArgs e)
{
this.onFormLoadTask = OnFormLoadTaskAsync(sender, e);
}
private async Task OnFormLoadTaskAsync(object sender, System.EventArgs e)
{
await Task.Delay(2000); // do async work
// ...
}
Run Code Online (Sandbox Code Playgroud)
除了可能的重入之外,异步事件处理程序的水下岩石是什么?
以下两段代码之间是否存在任何概念差异:
async Task TestAsync()
{
await Task.Run(() => DoSomeWork());
}
Run Code Online (Sandbox Code Playgroud)
和
Task TestAsync()
{
return Task.Run(() => DoSomeWork());
}
Run Code Online (Sandbox Code Playgroud)
生成的代码也不同吗?
编辑:为避免混淆Task.Run,类似的情况:
async Task TestAsync()
{
await Task.Delay(1000);
}
Run Code Online (Sandbox Code Playgroud)
和
Task TestAsync()
{
return Task.Delay(1000);
}
Run Code Online (Sandbox Code Playgroud)
最新更新:除了接受的答案之外,LocalCallContext处理方式也有所不同:即使没有异步,CallContext.LogicalGetData也会被恢复.为什么?
我想await在BlockingCollection<T>.Take()异步的结果,所以我不阻止线程.寻找这样的事情:
var item = await blockingCollection.TakeAsync();
Run Code Online (Sandbox Code Playgroud)
我知道我可以这样做:
var item = await Task.Run(() => blockingCollection.Take());
Run Code Online (Sandbox Code Playgroud)
但是有点杀死了整个想法,因为另一个线程ThreadPool被阻止了.
还有其他选择吗?
请看下面的代码 -
static void Main(string[] args)
{
// Get the task.
var task = Task.Factory.StartNew<int>(() => { return div(32, 0); });
// For error handling.
task.ContinueWith(t => { Console.WriteLine(t.Exception.Message); },
TaskContinuationOptions.OnlyOnFaulted);
// If it succeeded.
task.ContinueWith(t => { Console.WriteLine(t.Result); },
TaskContinuationOptions.OnlyOnRanToCompletion);
Console.ReadKey();
Console.WriteLine("Hello");
}
private static int div(int x, int y)
{
if (y == 0)
{
throw new ArgumentException("y");
}
return x / y;
}
Run Code Online (Sandbox Code Playgroud)
如果我在发布模式下执行代码,输出为"发生了一个或多个错误",一旦我点击"Enter"键,"Hello"也会显示.如果我在调试模式下运行代码,输出与但是在IDE中调试时,当控件执行该行时,会出现IDE异常消息("用户代码中未处理的异常")
throw new ArgumentException("y");
Run Code Online (Sandbox Code Playgroud)
如果我从那里继续,程序不会崩溃并显示与发布模式相同的输出.这是处理异常的正确方法吗?
我应该使用void 0或undefined在JavaScript中取消分配值,例如:
event.returnValue = void 0;
Run Code Online (Sandbox Code Playgroud)
要么
event.returnValue = undefined;
Run Code Online (Sandbox Code Playgroud) TL; DR:运行任务中的死锁StaTaskScheduler.长版:
我使用的是StaTaskScheduler从ParallelExtensionsExtras中通过平行小组,举办由第三方提供的一些遗留STA COM对象.StaTaskScheduler实现细节的描述如下:
好消息是TPL的实现能够在MTA或STA线程上运行,并考虑到底层API的相关差异,如WaitHandle.WaitAll(当方法提供多个等待句柄时,它只支持MTA线程).
我认为这意味着TPL的阻塞部分将使用等待API来提供消息,例如CoWaitForMultipleHandles,以避免在STA线程上调用时出现死锁情况.
在我的情况下,我相信发生以下情况:进程内STA COM对象A调用进程外对象B,然后期望从B通过回调作为传出调用的一部分.
以简化形式:
var result = await Task.Factory.StartNew(() =>
{
// in-proc object A
var a = new A();
// out-of-proc object B
var b = new B();
// A calls B and B calls back A during the Method call
return a.Method(b);
}, CancellationToken.None, TaskCreationOptions.None, staTaskScheduler);
Run Code Online (Sandbox Code Playgroud)
问题是,a.Method(b)永远不会回来.据我所知,这是因为内部阻塞等待BlockingCollection<Task>不会引发消息,因此我对引用语句的假设可能是错误的.
EDITED相同的代码工作测试WinForms应用程序的UI线程上执行时(即,提供TaskScheduler.FromCurrentSynchronizationContext()的,而不是staTaskScheduler到Task.Factory.StartNew).
解决这个问题的正确方法是什么?我应该实现一个自定义同步上下文,它将显式地使用消息CoWaitForMultipleHandles …
我知道我可以阻止Visual Studio调试器在抛出某些异常时停止(通过Ctrl-Alt-E"Exceptions"对话框).但是,如果想要从代码中控制这一点,对某些特定的地方而不是全部或全部基础呢?例如:
try
{
SomeMethod(token);
}
catch (OperationCancelledException)
{
return false;
}
// ...
void SomeMethod(CancellationToken token)
{
// ...
// I don't want the debugger to stop on the following line
#pragma ignore(OperationCancelledException, true)
token.ThrowIfCancellationRequested();
#pragma ignore(OperationCancelledException, false)
}
Run Code Online (Sandbox Code Playgroud)
我使用假设#pragma ignore来说明我的意思,但这样的事情确实存在吗?
更新以解决"不清楚你在问什么"关闭投票.在调试器中尝试以下代码:https://dotnetfiddle.net/npMk6r.确保在Ctrl-Alt-E对话框中启用了所有异常.调试器将throw new OperationCanceledException("cancelled1")在循环的每次迭代时停止在线上.我不希望这发生,因为它很烦人.然而,我确实希望它在循环外的最后一次投掷中停止throw new OperationCanceledException("cancelled2")(或者在其他地方,就此而言).
.net c# visual-studio task-parallel-library visual-studio-debugging
我想使用await Task.Run(DoWork),在ThreadPool上做一些重复的单线程计算工作.问题是,我需要在里面使用STA COM对象DoWork,所以我想我不能使用ThreadPool因为我不能改变池线程的公寓状态.
我怎样才能在这种情况下使用async/ await?使用自定义任务调度程序创建自己的STA线程池听起来像是一项过度的工作.
我需要禁用连接待机模式,直到我的桌面应用程序完成.所需的行为应与通过远程桌面连接到该计算机时发生的行为类似.也就是说,屏幕关闭,但系统在我断开连接之前不会进入睡眠状态.
是否有任何记录或未记录的方法来为我的应用程序获得相同的行为?
我试着PowerSetRequest用PowerRequestExecutionRequired和/或PowerRequestAwayModeRequired,但系统仍进入连接待机模式在少数分钟.我目前用PowerRequestDisplayRequired它来保持活着,但屏幕始终保持不变.
编辑.这是测试应用程序.按下硬件电源按钮并且屏幕关闭(使用电池运行)后,计时器滴答不超过5分钟.
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace CsTestApp
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
this.Load += MainForm_Load;
}
void MainForm_Load(object sender, EventArgs e)
{
// init timer
var timer = new System.Windows.Forms.Timer();
timer.Interval = 1000;
timer.Tick += delegate
{
System.Diagnostics.Trace.WriteLine("CsTestApp: " + DateTime.Now);
};
timer.Start();
// set GUID_EXECUTION_REQUIRED_REQUEST_TIMEOUT
IntPtr pActiveSchemeGuid;
var hr = PowerGetActiveScheme(IntPtr.Zero, out pActiveSchemeGuid);
if (hr != …Run Code Online (Sandbox Code Playgroud) c# ×9
.net ×8
async-await ×6
com ×2
asynchronous ×1
c++ ×1
collections ×1
events ×1
javascript ×1
task ×1
winapi ×1
windows ×1