相关疑难解决方法(0)

特殊的重载分辨率与while(true)

当我遇到这种特殊情况时,我正在实现同步/异步重载:

当我有一个没有参数或返回值的常规lambda表达式时,它会Run使用Action参数进行重载,这是可预测的.但是当lambda中有一个lambda时,while (true)它会通过Func参数进入重载状态.

public void Test()
{
    Run(() => { var name = "bar"; });
    Run(() => { while (true) ; });
}

void Run(Action action)
{
    Console.WriteLine("action");
}

void Run(Func<Task> func) // Same behavior with Func<T> of any type. 
{
    Console.WriteLine("func");
}
Run Code Online (Sandbox Code Playgroud)

输出:

动作
功能

那怎么可能呢?有原因吗?

.net c# lambda overloading overload-resolution

35
推荐指数
1
解决办法
830
查看次数

Lambda转换具有不明确的返回类型和重载决策

如果我有一个像() => { throw new Exception(); }这样的lambda ,则不清楚它是否有返回类型.因此,它可以(隐式)转换为ActionFunc<object>(或任何其他Func<T>).这是因为,根据§6.5C #4规范的匿名函数转换:

[A]委托类型D与提供的匿名功能兼容F:

  • ...

  • 如果D有一个void返回类型且body F是一个语句块,当[...]的主体F是一个有效的语句块时,其中没有return语句指定一个表达式.

  • 如果D具有非void返回类型且body F是一个语句块,则当[...]主体F是具有不可到达端点的有效语句块时,其中每个return语句指定一个可隐式转换为返回的表达式的类型D.

但是如果我有一个方法的两个重载,其中一个具有类型的参数Action和另一个Func<object>,并且我从上面传递lambda,Func<object>则使用重载.为什么?规范的哪一部分说Func<object>Action这种情况更好?

我已经看过§7.5.3.2 更好的函数成员,但这并没有解释它.

c# lambda overload-resolution

10
推荐指数
1
解决办法
341
查看次数

CancellationTokenSource的行为不符合预期

在这种情况下预期的是,如果用户通过按Enter键取消任务,则挂起的另一个任务ContinueWith将运行,但事实并非如此,AggregateException尽管显式处理ContinueWith显然没有被执行,但仍保持抛出.
请问下面的任何澄清?

class Program
{
    static void Main(string[] args)
    {
        CancellationTokenSource tokensource = new CancellationTokenSource();
        CancellationToken token = tokensource.Token;

        Task task = Task.Run(() =>
        {
            while (!token.IsCancellationRequested)
            {
                Console.Write("*");
                Thread.Sleep(1000);
            }
        }, token).ContinueWith((t) =>
        {
            t.Exception.Handle((e) => true);
            Console.WriteLine("You have canceled the task");
        }, TaskContinuationOptions.OnlyOnCanceled);

        Console.WriteLine("Press any key to cancel");
        Console.ReadLine();
        tokensource.Cancel();
        task.Wait();
    }
}
Run Code Online (Sandbox Code Playgroud)

.net c# multithreading task-parallel-library cancellation-token

5
推荐指数
1
解决办法
723
查看次数

为什么抛出OperationCanceledException会得到不同的结果?

我的同事玩TPL并取消任务.他向我展示了以下代码:

var cancellationToken = cts.Token;
var task = Task.Run(() =>
{
    while (true)
    {
        Thread.Sleep(300);
        if (cancellationToken.IsCancellationRequested)
        {
            throw new OperationCanceledException();
        }
    }

}, cancellationToken)
    .ContinueWith(t => {
        Console.WriteLine(t.Status);
    });

Thread.Sleep(200);
cts.Cancel();
Run Code Online (Sandbox Code Playgroud)

这版画"取消"符合市场预期,但如果你只是发表评论,而像这样的一行:

// ..
//while (true)
{
    Thread.Sleep(300);
    if (cancellationToken.IsCancellationRequested)
    {
        throw new OperationCanceledException();
    }
}
//..
Run Code Online (Sandbox Code Playgroud)

你会得到"故障".我很清楚ThrowIfCancellationRequested()方法,我应该在OperationCanceledException的构造函数中传递cancellationToken(在这两种情况下都会导致"取消"结果),但无论如何我无法解释为什么会发生这种情况.

c# task-parallel-library

5
推荐指数
1
解决办法
609
查看次数