小编avo*_*avo的帖子

为什么我更喜欢单个'await Task.WhenAll'多次等待?

如果我不关心任务完成的顺序,只需要完成它们,我还应该使用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

110
推荐指数
5
解决办法
6万
查看次数

我应该避免'async void'事件处理程序吗?

我知道使用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)

除了可能的重入之外,异步事件处理程序的水下岩石是什么?

.net c# events asynchronous async-await

108
推荐指数
4
解决办法
4万
查看次数

"await Task.Run(); return;"之间的任何区别 并"返回Task.Run()"?

以下两段代码之间是否存在任何概念差异:

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也会被恢复.为什么?

c# async-await

77
推荐指数
4
解决办法
3万
查看次数

是否有异步BlockingCollection <T>?

我想awaitBlockingCollection<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被阻止了.

还有其他选择吗?

.net c# collections task-parallel-library async-await

72
推荐指数
3
解决办法
2万
查看次数

在任务中继续处理异常的正确方法

请看下面的代码 -

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)

如果我从那里继续,程序不会崩溃并显示与发布模式相同的输出.这是处理异常的正确方法吗?

.net c# task task-parallel-library

52
推荐指数
4
解决办法
5万
查看次数

我应该在JavaScript中使用`void 0`或`undefined`

我应该使用void 0undefined在JavaScript中取消分配值,例如:

event.returnValue = void 0;
Run Code Online (Sandbox Code Playgroud)

要么

event.returnValue = undefined;
Run Code Online (Sandbox Code Playgroud)

javascript

27
推荐指数
2
解决办法
1万
查看次数

StaTaskScheduler和STA线程消息泵送

TL; DR:运行任务中的死锁StaTaskScheduler.长版:

我使用的是StaTaskSchedulerParallelExtensionsExtras中通过平行小组,举办由第三方提供的一些遗留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()的,而不是staTaskSchedulerTask.Factory.StartNew).

解决这个问题的正确方法是什么?我应该实现一个自定义同步上下文,它将显式地使用消息CoWaitForMultipleHandles …

.net c# com task-parallel-library async-await

27
推荐指数
2
解决办法
9314
查看次数

有选择地阻止调试器在第一次机会异常时停止

我知道我可以阻止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

13
推荐指数
1
解决办法
1297
查看次数

Async/await,ThreadPool和SetApartmentState

我想使用await Task.Run(DoWork),在ThreadPool上做一些重复的单线程计算工作.问题是,我需要在里面使用STA COM对象DoWork,所以我想我不能使用ThreadPool因为我不能改变池线程的公寓状态.

我怎样才能在这种情况下使用async/ await?使用自定义任务调度程序创建自己的STA线程池听起来像是一项过度的工作.

.net c# com multithreading async-await

12
推荐指数
1
解决办法
2817
查看次数

任何阻止Windows 8进入连接待机模式的API?

我需要禁用连接待机模式,直到我的桌面应用程序完成.所需的行为应与通过远程桌面连接到该计算机时发生的行为类似.也就是说,屏幕关闭,但系统在我断开连接之前不会进入睡眠状态.

是否有任何记录或未记录的方法来为我的应用程序获得相同的行为?

我试着PowerSetRequestPowerRequestExecutionRequired和/或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)

.net c# c++ windows winapi

11
推荐指数
1
解决办法
3949
查看次数