如何从多个异步任务串行访问单个设备?

问题描述 投票:0回答:1

我有单个外部资源 - 命名管道。我需要能够执行以下操作:

  • 几乎可以同时生成多个异步任务(通过 EXCEL-DNA 函数,在许多单元中运行)
  • 任务将尝试以任意方式获取对管道的访问权限(每个应用程序只能有一个管道)
  • 获胜任务将发送请求并等待响应,然后释放管道到下一个等待任务
  • 等待时间过长的任务应在超时后继续(返回“#err”值)
  • 我还不确定是否会从不同的线程触发任务(我是 excel-dna 的新手)

我不太想出一种优雅的方法来做到这一点(想到一件事 - 带超时的读/写锁)。

对于此类问题有纯异步解决方案吗?

c# async-await .net-6.0 excel-dna
1个回答
0
投票

您似乎可以使用队列来实现此目的,就像戴夫在评论中建议的那样。

TaskCompletionSource<TResult>
的帮助下,您可以创建自己的任务,您可以用我们自己的逻辑来完成这些任务。

以下是一个简单的不完整示例(未经测试),说明如何实现类似的功能:

public class PipeAccess
{
  private readonly ConcurrentQueue<ScheduledTask> _queue

  public Task<string> GetResult(string input) {
    var schedule = new ScheduledTask(input);
    _queue.Enqueue(schedule);
    return schedule.Completion.Task;
  }

  private sealed class ScheduledTask
  {
    private CancellationTokenSource _timeout;
    private IDisposable _timeoutRegistration;

    public ScheduleTask(string input)
    {
      Input = input;
      Completion = new TaskComletionSource<string>(TaskCreationOptions.RunContinuationsAsynchronously);
      _timeout = new CancellationTokenSource(TimeSpan.FromSeconds(30));
      _timeoutRegistration = _timeout.Token.Register(() => Completion.TrySetCancelled());
    }

    public string Input { get; }

    public TaskCompletionSource<string> Completion { get; }

    public bool StartProcessing()
    {
      _timeoutRegistration.Dispose();
      _timeout.Dispose();
      return !Completion.Task.IsCancelled;
    }
  }
}

在此示例中,我没有包含如何从队列中读取下一个任务的代码,但您首先调用

StartProcessing()
,以便停止超时。如果返回
false
,则该任务已超时,您可以转到队列中的下一项。否则你用管道做你的事情,结果可以设置为
Completion.TrySetResult()
,发生的任何错误都可以设置为
Completion.TrySetException()

我已经包含了

TaskCreationOptions.RunContinuationsAsynchronously
,因为否则等待
PipeAccess.GetResult()
的代码将在此线程上继续,使您的
PipeAccess
等到该代码完成后才能继续执行下一个排队任务(并增加超时的可能性)。

© www.soinside.com 2019 - 2024. All rights reserved.