Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# BufferBlock.ReceiveAsync(超时)挂起,但BufferBlock.ReceiveAsync()工作正常_C#_.net_Async Await_Task Parallel Library_Tpl Dataflow - Fatal编程技术网

C# BufferBlock.ReceiveAsync(超时)挂起,但BufferBlock.ReceiveAsync()工作正常

C# BufferBlock.ReceiveAsync(超时)挂起,但BufferBlock.ReceiveAsync()工作正常,c#,.net,async-await,task-parallel-library,tpl-dataflow,C#,.net,Async Await,Task Parallel Library,Tpl Dataflow,或者我做了一些非常错误的事情,但是下面的代码永远不会返回,它永远挂在ReceiveAsync上,尽管指定了1秒超时 我希望它在超时后返回空值 /* snipped MyContainer class */ private readonly BufferBlock<byte[]> queue = new BufferBlock<byte[]>(); public async Task ExecuteAsync(CancellationToken stoppingToke

或者我做了一些非常错误的事情,但是下面的代码永远不会返回,它永远挂在
ReceiveAsync
上,尽管指定了1秒超时

我希望它在超时后返回空值

/* snipped MyContainer class */

private readonly BufferBlock<byte[]> queue = new BufferBlock<byte[]>();

public async Task ExecuteAsync(CancellationToken stoppingToken)
{
     // makes no difference if creating with TaskCreationOptions.LongRunning
     await Task
            .Factory
            .StartNew(async () =>
            {

              while (stoppingToken.IsCancellationRequested == false)
              {                     
                 // we get here OK, but no further if i use TimeSpan for delay
                 // without Timespan i.e. ReceiveAsync() only, it does **not** hang
                 var item = await 
                             this
                               .queue
                               .ReceiveAsync(TimeSpan.FromMilliseconds(1000));

                      // process it, but we never get here we sleep forever
                      await ProcessAsync(item);
                    }
             } /*,TaskCreationOptions.LongRunning*/);

     // we get here and print the below OK
     Console.WriteLine("thread created and running");
}

// this is called by the original (or some other) thread
// either if i call this or not, the above thread code still locks on ReceiveAsync
public void Add(byte[] data)
{
   Console.WriteLine("adding");
   this.queue.Post(data);
   Console.WriteLine("done"); // gets posted OK     
}
如果我消除延迟,代码工作正常,但是我每秒都会进行一些后台管理(对于包计数器等),因此,如果在1秒内没有收到任何消息,那么这一点很重要

其他注意事项:

我正在从一个通用的dot net worker主机调用上述代码:

public class Worker : BackgroundService
{
    private readonly MyContainer containerClass;
    private readonly ILogger<Worker> logger;

    public Worker(MyContainer containerClass, ILogger<Worker> logger)
    {
        this.containerClass = containerClass;
        this.logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        this.containerClass.ExecuteAsync(stoppingToken);

        while (!stoppingToken.IsCancellationRequested)
        {                
            this.logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
        }
    }
}
public class Worker:BackgroundService
{
私有只读MyContainer容器类;
专用只读ILogger记录器;
公共工作者(MyContainer集装箱类、ILogger记录器)
{
this.container类=container类;
this.logger=记录器;
}
受保护的覆盖异步任务ExecuteAsync(CancellationToken stoppingToken)
{
this.containerClass.ExecuteAsync(stoppingToken);
同时(!stoppingToken.IsCancellationRequested)
{                
this.logger.LogInformation(“在:{time}运行的Worker”,DateTimeOffset.Now);
等待任务。延迟(1000,停止待命);
}
}
}
在工人由
IHostBuilder
构建之后调用上述函数,我调用了
Host.Run()


我的理解是(我显然需要处理!)因为我创建了线程,它应该完全独立于(而不是阻塞)创建/调用它的线程运行。。。换句话说,它应该能够在线程本身内调用ReceiveAsync,而不会被阻塞

感谢所有回复的人,最后感谢Enrico(请随意复制/粘贴,我会将答案分配给你),代码运行正常

正在引发TimeoutException异常,但我的代码或Visual Studio未捕获该异常

根据引发的异常启用所有CLR异常

然后,我在代码中处理了异常,并能够按照我的设计要求继续:

public Task ExecuteAsync(CancellationToken stoppingToken)
{
    return Task
            .Factory
            .StartNew(async () => {

                while (stoppingToken.IsCancellationRequested == false)
                {
                    try
                    {
                        var ts = TimeSpan.FromSeconds(UpdateFrequencySeconds);
                        var item = await this.queue.ReceiveAsync(ts);
                        await ProcessAsync(item);
                    }
                    catch (TimeoutException)
                    {
                        // this is ok, timer expired 
                    }
                    catch (Exception e)
                    {
                        this.logger.LogError(e.ToString());
                    }

                    UpdateCounters();
                }

                await StopAsync();
              },
              stoppingToken,
              TaskCreationOptions.LongRunning, 
              TaskScheduler.Default)
              .Unwrap();
 }

感谢所有回应的人,最后是Enrico(请随意复制/粘贴,我会将答案分配给你),代码实际上运行正常

正在引发TimeoutException异常,但我的代码或Visual Studio未捕获该异常

根据引发的异常启用所有CLR异常

然后,我在代码中处理了异常,并能够按照我的设计要求继续:

public Task ExecuteAsync(CancellationToken stoppingToken)
{
    return Task
            .Factory
            .StartNew(async () => {

                while (stoppingToken.IsCancellationRequested == false)
                {
                    try
                    {
                        var ts = TimeSpan.FromSeconds(UpdateFrequencySeconds);
                        var item = await this.queue.ReceiveAsync(ts);
                        await ProcessAsync(item);
                    }
                    catch (TimeoutException)
                    {
                        // this is ok, timer expired 
                    }
                    catch (Exception e)
                    {
                        this.logger.LogError(e.ToString());
                    }

                    UpdateCounters();
                }

                await StopAsync();
              },
              stoppingToken,
              TaskCreationOptions.LongRunning, 
              TaskScheduler.Default)
              .Unwrap();
 }

Task.Factory.StartNew
与异步委托一起使用可创建嵌套任务:

Task<Task> nestedTask = Task.Factory.StartNew(async () => { //...
或者,您可以使用该方法将两个任务合并为一个任务

…或者更好地使用该方法而不是
Task.Factory.StartNew
,因为前者理解异步委托,并为您执行展开:

await Task.Run(async () => { //...

如果您对
Task.Factory.StartNew
Task.Run
之间的差异感兴趣,您可以阅读一篇信息性文章。

使用带有异步委托的
Task.Factory.StartNew
创建嵌套任务:

Task<Task> nestedTask = Task.Factory.StartNew(async () => { //...
或者,您可以使用该方法将两个任务合并为一个任务

…或者更好地使用该方法而不是
Task.Factory.StartNew
,因为前者理解异步委托,并为您执行展开:

await Task.Run(async () => { //...

如果您对
Task.Factory.StartNew
Task.Run
之间的差异感兴趣,您可以阅读一篇信息性文章。

您是否在某处调用了
.Result
.Wait
Result
在你的呼叫堆栈上的任何地方?是的,你是对的!我现在发现了这个例外。我不知道为什么它没有显示为未经visual studio处理。我还要做一些digging@g18c因为您可能需要要求VS调试器在每个CLR异常上中断。您需要在VS.@g18c中的调试器->选项窗口中执行此操作。在调查您的问题并对其进行全面了解后,请记住更新您的问题,并对问题进行最终解释,以便每位临时读者都能对问题进行全面了解。很多用户可能会跳过评论,直接阅读问题。您是否在某个地方调用了
.Result
.Wait
?您是否在调用堆栈上的任何位置阻塞(即使用
Wait
Result
)了?是的,您是对的!我现在发现了这个例外。我不知道为什么它没有显示为未经visual studio处理。我还要做一些digging@g18c因为您可能需要要求VS调试器在每个CLR异常上中断。您需要在VS.@g18c中的调试器->选项窗口中执行此操作。在调查您的问题并对其进行全面了解后,请记住更新您的问题,并对问题进行最终解释,以便每位临时读者都能对问题进行全面了解。很多用户可能会跳过评论,直接阅读问题。很棒的东西,会改变它,可以看到它是如何导致问题的。很多人会改变它,可以看到它是如何导致问题的