Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.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# 如何将失败的后台异步任务重新排队_C#_Asp.net Core_Asp.net Core Mvc_Asp.net Core 2.2 - Fatal编程技术网

C# 如何将失败的后台异步任务重新排队

C# 如何将失败的后台异步任务重新排队,c#,asp.net-core,asp.net-core-mvc,asp.net-core-2.2,C#,Asp.net Core,Asp.net Core Mvc,Asp.net Core 2.2,您好,我正在尝试使用BackgroundService创建一个在后台执行的通用任务队列服务。我避免使用DelegatefunctionFunc作为EnqueueTask(Task newTask)方法的输入,因为我想要一个通用的解决方案,所以我选择传递一个Task。但此解决方案不允许我在ExecuteAsync(CancellationToken stoppingToken)中重新排队失败的任务,因为该任务返回的ResponseHelper实例不是失败任务的副本。请帮助我更正代码,我必须从deq

您好,我正在尝试使用
BackgroundService
创建一个在后台执行的通用任务队列服务。我避免使用
Delegate
function
Func
作为
EnqueueTask(Task newTask)
方法的输入,因为我想要一个通用的解决方案,所以我选择传递一个
Task
。但此解决方案不允许我在
ExecuteAsync(CancellationToken stoppingToken)
中重新排队失败的任务,因为该任务返回的
ResponseHelper
实例不是失败任务的副本。请帮助我更正代码,我必须从
dequeuetasksync(CancellationToken CancellationToken)
函数返回一个出列任务,而不是
ResponseHelper
的实例

public interface ITaskQueueHelper
{
    void EnqueueTask(Task<ResponseHelper> newTask);

    Task<ResponseHelper> DequeueTaskAsync(CancellationToken cancellationToken);
}

public class TaskQueueHelper : ITaskQueueHelper
{
    private readonly SemaphoreSlim signal;

    private readonly ConcurrentQueue<Task<ResponseHelper>> taskQueue;

    public TaskQueueHelper()
    {
        signal = new SemaphoreSlim(0);

        taskQueue = new ConcurrentQueue<Task<ResponseHelper>>();
    }

    public void EnqueueTask(Task<ResponseHelper> newTask)
    {
        if (newTask == null)
        {
            throw new ArgumentNullException(nameof(newTask));
        }

        taskQueue.Enqueue(newTask);

        signal.Release();
    }

    public async Task<ResponseHelper> DequeueTaskAsync(CancellationToken cancellationToken)
    {
        await signal.WaitAsync(cancellationToken);

        taskQueue.TryDequeue(out var currentTask);

        /*I need to return currentTask here, instead of an instance of ResponseHelper*/

        return await currentTask;
    }
}

public class TaskQueueService : BackgroundService
{
    private readonly ITaskQueueHelper taskQueue;

    private readonly ILogger<TaskQueueService> logger;

    public TaskQueueService(
        ITaskQueueHelper _taskQueue,
        ILogger<TaskQueueService> _logger)
    {
        logger = _logger;

        taskQueue = _taskQueue;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            ResponseHelper response = await taskQueue.DequeueTaskAsync(stoppingToken);

            try
            {
                if (!response.Status.Equals(ResultCode.Success))
                {
                    /*I need to re-enqueue a failed task here*/

                    //taskQueue.EnqueueTask(currentTask);
                }
            }
            catch (Exception e)
            {
                logger.LogError(e, $"Error occurred executing {nameof(TaskQueueService)}");
            }
        }
    }
}
公共接口ITaskQueueHelper
{
无效排队任务(任务新任务);
任务出列TaskAsync(CancellationToken CancellationToken);
}
公共类TaskQueueHelper:ITaskQueueHelper
{
专用只读信号量LIM信号;
私有只读ConcurrentQueue任务队列;
公共TaskQueueHelper()
{
信号=新信号量lim(0);
taskQueue=新的ConcurrentQueue();
}
公共void排队任务(任务newTask)
{
if(newTask==null)
{
抛出新ArgumentNullException(nameof(newTask));
}
taskQueue.Enqueue(newTask);
信号。释放();
}
公共异步任务出列TaskAsync(CancellationToken CancellationToken)
{
wait signal.WaitAsync(cancellationToken);
TryDequeue(out var currentTask);
/*我需要在这里返回currentTask,而不是ResponseHelper的实例*/
返回等待当前任务;
}
}
公共类TaskQueueService:BackgroundService
{
专用只读ITaskQueueHelper任务队列;
专用只读ILogger记录器;
公共任务队列服务(
ITaskQueueHelper\u任务队列,
ILogger(记录器)
{
记录器=_记录器;
taskQueue=\u taskQueue;
}
受保护的覆盖异步任务ExecuteAsync(CancellationToken stoppingToken)
{
同时(!stoppingToken.IsCancellationRequested)
{
ResponseHelper response=wait taskQueue.dequeuetasksync(stoppingToken);
尝试
{
如果(!response.Status.Equals(ResultCode.Success))
{
/*我需要将失败的任务重新排队*/
//taskQueue.EnqueueTask(当前任务);
}
}
捕获(例外e)
{
logger.LogError(e,$”执行{nameof(TaskQueueService)}时出错);
}
}
}
}

对于重试,您可以执行以下操作:


    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            ResponseHelper response = await taskQueue.DequeueTaskAsync(stoppingToken);

            try
            {
                if (!response.Status.Equals(ResultCode.Success))
                {
                    // Retry the task.
                    response = await taskQueue.DequeueTaskAsync(stoppingToken);

                }
            }
            catch (Exception e)
            {
                logger.LogError(e, $"Error occurred executing {nameof(TaskQueueService)}");
            }
        }
    }


对于重试,您可以执行以下操作:


    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            ResponseHelper response = await taskQueue.DequeueTaskAsync(stoppingToken);

            try
            {
                if (!response.Status.Equals(ResultCode.Success))
                {
                    // Retry the task.
                    response = await taskQueue.DequeueTaskAsync(stoppingToken);

                }
            }
            catch (Exception e)
            {
                logger.LogError(e, $"Error occurred executing {nameof(TaskQueueService)}");
            }
        }
    }


只是提醒一下,如果你需要工作,我已经成功地使用了hangfire来代替。@Sommen谢谢你的提醒,如果我没有从其他软件工程师那里得到工作,我会考虑这个问题。wel很难理解你在这里做什么。我的意思是,如果您想重新查询任务,您需要保留对它的引用,因此需要将它添加到您的响应中,或者您的调度服务应该保留对它的引用。没有别的了way@sommmen我试图使用
EnqueueTask(Task newTask)
将任务添加到队列中,而不是通过
Delegate
添加任务,任务返回类型为
ResponseHelper
的实例,但当
dequeuetasksync(CancellationToken CancellationToken)时
函数运行
返回等待当前任务它返回ResponseHelper的实例,而不是当前已退出队列的任务。我希望此函数返回currentTask。这就是我需要解决的问题。
因为integerTask是一个任务,所以它包含一个TResult类型的Result属性。在本例中,TResult表示整数类型。当wait应用于integerTask时,wait表达式的计算结果为integerTask的Result属性的内容。该值分配给ret变量。
来自msdn。你看,这不是怎么回事。只是提醒一下,如果你需要工作,我已经成功地使用了hangfire来代替。@Sommen谢谢你的提醒,如果我没有从其他软件工程师那里得到一份工作,我会考虑这个问题。wel很难理解你在这里做什么。我的意思是,如果您想重新查询任务,您需要保留对它的引用,因此需要将它添加到您的响应中,或者您的调度服务应该保留对它的引用。没有别的了way@sommmen我试图使用
EnqueueTask(Task newTask)
将任务添加到队列中,而不是通过
Delegate
添加任务,任务返回类型为
ResponseHelper
的实例,但当
dequeuetasksync(CancellationToken CancellationToken)时
函数运行
返回等待当前任务它返回ResponseHelper的实例,而不是当前已退出队列的任务。我希望此函数返回currentTask。这就是我需要解决的问题。
因为integerTask是一个任务,所以它包含一个TResult类型的Result属性。在本例中,TResult表示整数类型。当wait应用于integerTask时,wait表达式的计算结果为integerTask的Result属性的内容。该值分配给ret变量。
来自msdn。你看,这不是它的工作原理。这将重试一次任务,你可以做一个while循环来做几次。还可以查看polly以重试。它是一个流行的库和.NET基础的一部分。在<代码> IaskQuealeHelpServer接口< /CudithSoad >中添加属性的想法是怎样的?code>public Task ExecutingTask{set;get;}
并分配一个出列任务的副本。然后我可以执行类似以下操作
taskQueue.EnqueueTask(taskQueue.ExecutingTask)。“你对这件事有什么想法吗?”我说