【问题标题】:Using BackgroundWorker instead of queuing使用 BackgroundWorker 而不是排队
【发布时间】:2023-03-28 21:14:01
【问题描述】:

场景 我有一个客户端必须同步调用我的 Web 服务,并且我必须在三秒内做出响应。我的网络服务同步调用另一个通常需要大约 12 秒。

为了简单和时间限制,我正在考虑使用 BackgroundWorker 而不是实现排队。我有理由相信这是一个一次性的场景,它可能看到的最重的交易量将是每天大约 100 个。因此,我不认为有关分拆流程数量的常见问题令人担忧。

我读过的相关主题将其作为一种选择,但通常不是首选。

问题 这是一个适合背景工作者的场景吗?尤其是因为我没有大量使用 MSMQ 也没有很长时间

【问题讨论】:

  • 不要用这个来打扰 Web 服务端点。它应该真正将在自己的进程中独立运行的后台作业排入队列(除非您在 Core 上,您可以使用 BackgroundService 作为 documented here
  • 在您的应用程序崩溃或服务器停机进行维护之前,使用后台工作人员会很好。我没有看到队列比启动和管理后台工作人员更复杂。 “一次性场景”不要相信谎言!
  • 很公平。时间线并不像最初想象和同意的那样紧迫,排队也不是怪物。我已经被依赖未内置的组件咬了很多次(哦,我们也没有在 UAT 上打开 MSMQ。你真的想要那些一致的吗???)。 @Dan Wilson,谎言确实是一种危险。

标签: c# wcf message-queue


【解决方案1】:

你可以做这样的事情。发出请求时,在并发字典中添加参数,这些参数需要调用服务,需要 12 秒。返回响应。然后在后台你可以使用类似的东西在后台做这项工作。不需要做不同的过程等。

public static class BackGroundWorker
{
    private static Thread WorkerThread = null;

    private static readonly object WorkerLock = new object();

    private static readonly ManualResetEventSlim ShutdownEvent = new ManualResetEventSlim(false);

    private static ConcurrentDictionary<string, string> backGroundExecutingRequestIds = new ConcurrentDictionary<string, string>();

    public static void Start()
    {
        if (WorkerThread != null)
        {
            return;
        }

        lock (WorkerLock)
        {
            if (WorkerThread != null)
            {
                return;
            }

            ShutdownEvent.Reset();
            WorkerThread = new Thread(new ThreadStart(WorkerThreadProc));
            WorkerThread.Start();
        }
    }

    public static void Stop()
    {
        if (WorkerThread == null)
        {
            return;
        }

        ShutdownEvent.Set();
        WorkerThread.Join();
        WorkerThread = null;
    }

    private static void WorkerThreadProc() => WorkerThreadProcAsync().Wait();

    private static async Task WorkerThreadProcAsync()
    {
        try
        {
            while (!ShutdownEvent.Wait(0))
            {
                var ids = backGroundExecutingRequestIds.Take(25)?.Select(item => item.Key)?.ToList();
                while (ids?.Count > 0)
                {
                    //// Do the work of calling external Service which takes 12 seconds.
                    ids = Get the Next 25 Ids
                }

                await Task.Delay(TimeSpan.FromMilliseconds(100));
            }
        }
        catch(Exception ex)
        {
           ////LogException
        }
    }
}

}

【讨论】:

    猜你喜欢
    • 2013-02-13
    • 1970-01-01
    • 2023-03-30
    • 2010-11-02
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 2019-02-19
    相关资源
    最近更新 更多