Прошу прощения за то, что я размещаю здесь этот длинный код, но у меня нет другого способа помочь вам воспроизвести мою проблему. Код, который я вам даю, конечно, является миниатюрой того, что я использую. Я знаю, что могу использовать QueueUserWorkItem
, и я использовал его до недавнего времени, но я понял, что мои потоки настолько коротки, что мой метод ThreadDispatcher
не запускал второй, прежде чем первый закончен. Поэтому я пытаюсь понять, работает ли этот способ быстрее или нет. Проблема в том, что у меня есть тупик, и я действительно не могу понять, почему. Я отправляю код, который вы можете напрямую компилировать и воспроизводить.Многопользовательский тупик на домашнем пуле для нитей в C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace TestWhatever
{
public class Program
{
static MyClass ThisClass = new MyClass();
static void Main()
{
ThisClass.Start();
for (int Cnt = 0; Cnt < 5; Cnt++)
{
Console.WriteLine("Launching Frame " + Cnt);
ThisClass.Update();//Frames loop
}
}
}
public class MyClass
{
Random MyRandom = new Random();
public static object _MultiDispatcherLocker = new object();
public static bool MonoDispacherThreadLocked = true;
public static bool MultiDispacherThreadLocked = true;
// Thread pool in multithreading case
private int MaxThreadsInParallel = 5;
private static int MaxNumOfPool = 20;
private Thread[] ThreadsPool;
public static object _ThreadLockerList;
private Func<string>[] ThreadFunctions;
public bool[] ThreadLockedBools = Enumerable.Repeat(true, MaxNumOfPool).ToArray();
public void Start()
{
StartThreads();
}
public void Update()
{
lock (_MultiDispatcherLocker)
{
MultiDispacherThreadLocked = false;
Monitor.Pulse(_MultiDispatcherLocker);
}
Thread.Sleep(1000);
}
private void StartThreads()
{
ThreadsPool = new Thread[MaxNumOfPool];
_ThreadLockerList = new object();
ThreadFunctions = new Func<string>[MaxNumOfPool];
ThreadLockedBools = new bool[MaxNumOfPool];
for (int Cnt = 0; Cnt < MaxNumOfPool; Cnt++)
{
Console.WriteLine("Preparing ThreadID: " + Cnt);
ThreadLockedBools[Cnt] = true;
ThreadsPool[Cnt] = new Thread(new ParameterizedThreadStart(LaunchThread));
ThreadsPool[Cnt].Start(Cnt);
}
Thread ThreadedMainThread = new Thread(new ThreadStart(ThreadDispatcher));
ThreadedMainThread.Start();
ThreadedMainThread.Priority = System.Threading.ThreadPriority.Highest;
}
private void LaunchThread(object iThreadID)
{
int ThreadID = (int)iThreadID;
lock (_ThreadLockerList)
{
while (ThreadLockedBools[ThreadID])
Monitor.Wait(_ThreadLockerList);
}
while (true)
{
Console.WriteLine("Starting ThreadID: " + ThreadID);
ThreadFunctions[ThreadID]();
Console.WriteLine("Ending ThreadID: " + ThreadID);
lock (_MultiDispatcherLocker)
{
ThreadLockedBools[ThreadID] = true;
MultiDispacherThreadLocked = false;
Monitor.Pulse(_MultiDispatcherLocker);
}
lock (_ThreadLockerList)
{
Console.WriteLine("Blocking ThreadID: " + ThreadID);
while (ThreadLockedBools[ThreadID])
Monitor.Wait(_ThreadLockerList);
}
}
}
private void ThreadDispatcher()//object Obj)
{
lock (_MultiDispatcherLocker)
{
while (MultiDispacherThreadLocked)
Monitor.Wait(_MultiDispatcherLocker);
}
while (true)
{
for (int Cnt = 0; Cnt < 20; Cnt++)//Threads loop
{
if (RunningThreads() < MaxThreadsInParallel)
{
int CurrIntTest = MyRandom.Next(100000, 10000000);
int ThreadID = GetNextEmptyThread();
ThreadFunctions[ThreadID] =() => { MyMethodInThread(CurrIntTest); return null; };
lock (_ThreadLockerList)
{
ThreadLockedBools[ThreadID] = false;
Monitor.Pulse(_ThreadLockerList);
}
}
else//wait until someone ends
{
lock (_MultiDispatcherLocker)
{
while (MultiDispacherThreadLocked)
{
Monitor.Wait(_MultiDispatcherLocker);
}
}
}
}
lock (_MultiDispatcherLocker)
{
MultiDispacherThreadLocked = true;
while (MultiDispacherThreadLocked)
Monitor.Wait(_MultiDispatcherLocker);
}
}
}
private void MyMethodInThread(int Counter)
{
List<string> MyDummy = new List<string>();
for (int Cnt = 0; Cnt < Counter; Cnt++) MyDummy.Add("Dummy");
}
private int RunningThreads()
{
int ToReturn = 0;
for (int Cnt = 0; Cnt < MaxThreadsInParallel; Cnt++)
{
if (!ThreadLockedBools[Cnt] || ThreadsPool[Cnt].ThreadState != System.Threading.ThreadState.WaitSleepJoin)
ToReturn++;
}
return ToReturn;
}
private int GetNextEmptyThread()
{
for (int Cnt = 0; Cnt < MaxThreadsInParallel; Cnt++)
{
if (ThreadLockedBools[Cnt] && ThreadsPool[Cnt].ThreadState == System.Threading.ThreadState.WaitSleepJoin)
return Cnt;
}
return -1;
}
}
}
было бы действительно здорово, если бы вы могли мне помочь.
Вы разработали его, исправьте. Явное микро-управление потоками печально известно, что 1) идет не так, и 2) будучи неуязвимым, когда это делает :( –