gpt4 book ai didi

c# - 取消处于阻塞状态的任务的最佳方法是什么?

转载 作者:行者123 更新时间:2023-11-30 16:59:14 24 4
gpt4 key购买 nike

我有一些运行的任务调用了从 RabbitMQ 读取的方法。当队列中没有任何内容时,该方法就会阻塞。因此任务具有“运行”状态,但实际上并未执行任何操作。有没有办法优雅地结束这些任务?

访问队列的代码如下:

 private void FindWork(CancellationToken ct)
{
if (ct.IsCancellationRequested)
return;

bool result = false;
bool process = false;
bool queueResult = false;
Work_Work work = null;

try
{
using (Queue workQueue = new Queue(_workQueue))
{
// Look for work on the work queue
workQueue.Open(Queue.Mode.Consume);
work = workQueue.ConsumeWithBlocking<Work_Work>();

// Do some work with the message ...

return;

任务创建如下:

private void Run()
{
while (!_stop)
{
// Remove and stopped tasks from the pool
List<int> removeThreads = new List<int>();

lock (_tasks)
{
foreach (KeyValuePair<int, Task> task in _tasks)
{
if (task.Value.Status != TaskStatus.Running)
{
task.Value.Wait();
removeThreads.Add(task.Value.Id);
}
}

foreach (int taskID in removeThreads)
_tasks.Remove(taskID);
}

CancellationToken ct = _cts.Token;
TaskFactory factory = new TaskFactory(ct, TaskCreationOptions.LongRunning, TaskContinuationOptions.LongRunning, null);

// Create new tasks if we have room in the pool
while (_tasks.Count < _runningMax)
{
Task task = factory.StartNew(() => FindWork(ct));

lock (_tasks)
_tasks.Add(task.Id, task);
}

// Take a rest so we don't run the CPU to death
Thread.Sleep(1000);
}
}

目前,我已将任务创建代码更改为如下所示,以便我可以中止任务。我知道这不是一个好的解决方案,但我不知道还能做什么。

while (_tasks.Count < _runningMax)
{
Task task = factory.StartNew(() =>
{
try
{
using (_cts.Token.Register(Thread.CurrentThread.Abort))
{
FindWork(ct);
}
}
catch (ThreadAbortException)
{
return;
}
}, _cts.Token);

_tasks.Add(task.Id, task);
}

最佳答案

以下是否适用于您的场景?

我不会生成多个线程并让它们在队列中等待,而是让一个线程处于无限轮询循环中,并在新的工作片段进入时让该线程生成一个新线程。您可以将信号量添加到限制您创建的线程数。检查下面的示例代码,我使用了 BlockingCollection 而不是 RabbitMQ。

  public class QueueManager
{
public BlockingCollection<Work> blockingCollection = new BlockingCollection<Work>();
private const int _maxRunningTasks = 3;

static SemaphoreSlim _sem = new SemaphoreSlim(_maxRunningTasks);

public void Queue()
{
blockingCollection.Add(new Work());
}

public void Consume()
{
while (true)
{
Work work = blockingCollection.Take();

_sem.Wait();

Task t = Task.Factory.StartNew(work.DoWork);
}
}

public class Work
{
public void DoWork()
{
Thread.Sleep(5000);
_sem.Release();
Console.WriteLine("Finished work");
}
}
}

和我的测试类

class Test
{
static void Main(string[] args)
{
Consumer c = new Consumer();
Task t = Task.Factory.StartNew(c.Consume);

c.Queue();
c.Queue();
c.Queue();
c.Queue();
c.Queue();

Thread.Sleep(1000);
Console.ReadLine();
}
}

关于c# - 取消处于阻塞状态的任务的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23913358/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com