为了账号安全,请及时绑定邮箱和手机立即绑定

asp.net core 中的排队任务

asp.net core 中的排队任务

C#
烙印99 2021-08-22 17:31:11
例如功能 有 20 个用户,他们几乎一次点击了发送按钮,所以方法堆叠在队列中,第一个用户消息被发送并收到响应,在第二个第三个之后,依此类推。用户不会与其他人聊天,但使用响应非常快的设备所以我试图将发送消息的任务排队。我找到了使用任务队列的代码示例,如示例 1和示例 2 所示。示例 1public class SerialQueue{    readonly object _locker = new object();    WeakReference<Task> _lastTask;    public Task Enqueue(Action action)    {        return Enqueue<object>(() => {            action();            return null;        });    }    public Task<T> Enqueue<T>(Func<T> function)    {        lock (_locker)        {            Task lastTask = null;            Task<T> resultTask = null;            if (_lastTask != null && _lastTask.TryGetTarget(out lastTask))            {                resultTask = lastTask.ContinueWith(_ => function());            }            else            {                resultTask = Task.Run(function);            }            _lastTask = new WeakReference<Task>(resultTask);            return resultTask;        }    }}示例 2 public class TaskQueue{    private readonly SemaphoreSlim _semaphoreSlim;    public TaskQueue()    {        _semaphoreSlim = new SemaphoreSlim(1);    }    public async Task<T> Enqueue<T>(Func<Task<T>> taskGenerator)    {        await _semaphoreSlim.WaitAsync();        try        {            return await taskGenerator();        }        finally        {            _semaphoreSlim.Release();        }    }    public async Task Enqueue(Func<Task> taskGenerator)    {        await _semaphoreSlim.WaitAsync();        try        {            await taskGenerator();        }        finally        {            _semaphoreSlim.Release();        }    }}问题是,当我每次按下按钮时传递我想要排队的任务(示例 3)时,任务仍然同时执行并相互中断。我如何解决问题并将任务堆叠到每次单击时排队?
查看完整描述

1 回答

?
DIEA

TA贡献1820条经验 获得超2个赞

你的问题是,你创建一个新的TaskQueue和SerialQueue每次。这样每次用户点击/调用PostMessage都会创建一个新的队列,任务是队列中的第一个任务,直接执行。


您应该使用静态/单例队列,以便每次单击/调用都适用于同一个队列对象。


但是,当您跨多个服务器扩展 Web 应用程序时,这会带来问题。为此,您应该将诸如(例如)Azure 队列存储之类的东西与 Azure Functions 结合使用。


启动文件

public void ConfigureServices(IServiceCollection services)

{

    services.AddSingleton<TaskQueue>();

    services.AddSingleton<SerialQueue>();

    // the rest

}

一些控制器.cs

[HttpPost(Name = "add-message")]

public async Task<IActionResult> PostMessage(

    [FromBody] MessengerViewModel messengerViewModel,

    [FromServices] TaskQueue taskQueue,

    [FromServices] SerialQueue serialQueue)

{

    await taskQueue.Enqueue(

        () => SendMessage(

                  messengerViewModel.PhoneNr, 

                  messengerViewModel.MessageBody,

                  messengerViewModel.ContactId, 

                  messengerViewModel.State));

    //I'm not running tasks at same time, using one or other at time

    await serialQueue.Enqueue(

        () => SendMessage(

                  messengerViewModel.PhoneNr, 

                  messengerViewModel.MessageBody,

                  messengerViewModel.ContactId, 

                  messengerViewModel.State));


    return Ok();

}


查看完整回答
反对 回复 2021-08-22
  • 1 回答
  • 0 关注
  • 460 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信