【问题标题】:.NET client-side WCF with queued requests具有排队请求的 .NET 客户端 WCF
【发布时间】:2022-08-19 13:36:50
【问题描述】:

背景

我正在更新旧版软件库。遗留代码使用无限循环 System.Threading.Thread 执行队列中的进程。这些进程对另一个只能处理一个请求的遗留系统执行多个请求。

我正在尝试现代化,但我是 WCF 服务的新手,我的知识中可能存在一个可以简化事情的大漏洞。

WCF 客户端主机

在现代化过程中,我正在尝试迁移到客户端 WCF 服务。 WCF 服务允许对来自多个应用程序的请求进行排队。该服务接受一个请求并返回一个 GUID,以便我可以通过回调正确关联。

public class SomeService : ISomeService
{
    public Guid AddToQueue(Request request)
    {
    // Code to add the request to a queue, return a Guid, etc.
    }
}

public interface ISomeCallback
{
    void NotifyExecuting(Guid guid)
    void NotifyComplete(Guid guid)
    void NotifyFault(Guid guid, byte[] data)
}

WCF 客户端进程队列

我遇到的问题是遗留流程可以包含多个请求。进程 1 可能会执行请求 X,然后执行请求 Y,并根据这些结果跟进请求 Z。对于遗留系统,可能会有进程 1-10 排队。

我有一个执行该过程的笨拙模型。我正在处理进程中的事件,以了解它何时完成或失败。但是,感觉真的很坑爹……

public class ActionsQueue
{
    public IList<Action> PendingActions { get; private set; }
    public Action CurrentAction { get; private set; }

    public void Add(Action action)
    {
        PendingAction.Add(action)
        if (CurrentAction is null)
            ExecuteNextAction();
    }

    private void ExecuteNextAction()
    {
        if (PendingActions.Count > 0)
        {
            CurrentAction = PendingActions[0];
            PendingActions.RemoveAt(0);
            CurrentAction.Completed += OnActionCompleted;
            CurrentAction.Execute();
        }
    }

    private OnActionCompleted(object sender, EventArgs e)
    {
        CurrentAction = default;
        ExecuteNextAction();
    }
}

public class Action
{
    internal void Execute()
    {
    // Instantiate the first request
    // Add handlers to the first request
    // Send it to the service
    }

    internal void OnRequestXComplete()
    {
    // Use the data that\'s come back from the request
    // Proceed with future requests
    }
}

通过客户端回调,GUID 与原始请求相匹配,并在原始请求上引发相关事件。同样,这里的实现感觉真的很笨拙。

我已经看到主机的异步方法示例,返回一个任务,然后在任务上使用等待。但是,我也看到了不这样做的建议。

任何关于如何将这种混乱解开成更有用的东西的建议都值得赞赏。同样,我的知识可能存在一个漏洞,这使我无法找到更好的解决方案。

谢谢

    标签: c# .net wcf asynchronous


    【解决方案1】:

    WCF 的客户端和服务器之间的队列通信通常可以使用 NetMsmqbinding 进行,它确保客户端和服务器之间的持久通信。具体示例见this article

    如果您需要高效快速的消息处理,请使用非事务性队列并将 ExactlyOnce 属性设置为 False,但这会影响安全。检查this docs 了解更多信息。

    【讨论】:

      【解决方案2】:

      万一有人后来遇到类似的问题,这是我最终得到的粗略草图:

      [ServiceContract(Name="MyService", SessionMode=Session.Required]
      public interface IMyServiceContract
      {
          [OperationContract()]
          Task<string> ExecuteRequestAsync(Action action);
      }
      
      public class MyService: IMyServiceContract
      {
          private TaskQueue queue = new TaskQueue();
          public async Task<string> ExecuteRequestAsync(Request request)
          {
              return await queue.Enqueue(() => request.Execute());
          }
      }
      
      public class TaskQueue
      {
          private SemaphoreSlim semaphore;
      public TaskQueue()
          {
              semaphore = new SemaphoreSlim(1);
          }
      
          Task<T> Enqueue<T>(Func<T> function)
          {
              await semaphore.WaitAsync();
              try
              {
                  return await Task.Factory.StartNew(() => function.invoke();)
              }
              finally
          {
                  semaphore.Release();
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-19
        • 1970-01-01
        • 2021-08-21
        • 1970-01-01
        • 2012-07-28
        • 1970-01-01
        相关资源
        最近更新 更多