为什么我的线程变成死锁c#
本文关键字:死锁 我的 线程 为什么 | 更新日期: 2023-09-27 18:06:48
我在一个应用程序中遇到了多线程问题。
流程基本上包括需要处理的项目列表。作为此处理的一部分,需要调用不支持多线程的第三方api。
我试图引入API类的单例实例,并使用锁定来确保一次只有一个线程调用它,但我仍然遇到这样的情况:一个线程在调用API时卡住了,而其他线程则卡住了,等待锁被释放。
如果我暂停调试会话并检查线程的调用堆栈,则对API调用进行调用的线程有以下跟踪:
mscorlib.dll ! System.Threading.WaitHandle.WaitAll (System.Threading。waitthandle [] waitthandle, int毫秒超时,bool退出上下文
mscorlib.dll ! System.Threading.WaitHandle.WaitAll (System.Threading。waitthandle [] waitthandles)
我已经在单个线程上测试了这一点,通过显式调用Process方法交换foreach循环中的线程池,它工作得很好(尽管比我想要的慢,在API调用之前和之后有相当多的处理)。
是我在这里做错了什么,还是这是第三方api的问题?
public class MyClass
{
private static ThirdPartyApi ApiInstance;
private static object lockObject = new object();
...
public void DoWork(list)
{
...
foreach (var item in list)
{
ThreadPool.QueueUserWorkItem(Process, item);
}
...
}
public void Process(string item)
{
// Various processing
...
lock(lockObject)
{
var result = ApiInstance.Lookup(item);
}
...
}
线程不安全的代码并不一定意味着方法不可重入,一些线程不安全的库要求所有调用来自同一个线程,就这样。试试下面使用BlockingCollection的方法,它将在同一个线程上发出所有调用,看看它是否解决了这个问题。
public class MyClass<T>
{
private BlockingCollection<T> workQueue = new BlockingCollection<T>();
public MyClass()
{
Task.Factory.StartNew(ProcessWorkQueue, TaskCreationOptions.LongRunning);
}
public void DoWork(List<T> work)
{
foreach (var workItem in work)
{
workQueue.Add(workItem);
}
}
public void StopWork()
{
workQueue.CompleteAdding();
}
public void ProcessWorkQueue()
{
foreach(var item in workQueue.GetConsumingEnumerable())
{
//Do something here
}
}
}
同样,ThreadPool是一个共享资源,对ThreadPool线程执行任何阻塞操作都会耗尽它。即使您的代码可以正常工作,也需要对其进行重构以解决这个资源匮乏问题。