/ / WaitOne () czeka wiecznie, mimo że wszystkie zdarzenia zostały uruchomione - c #, wielowątkowość, waitone

WaitOne () czeka wiecznie, nawet jeśli wszystkie zdarzenia zostały uruchomione - c #, wielowątkowość, waitone

Threaded ma założyć 4 oddzielnewątki i poczekaj na każdy z nich, aż zakończą. Każdy wątek śpi przez chwilę i kończy się tylko wtedy, gdy udostępniony obiekt Mutex nie jest zajęty przez inny wątek, a następnie sygnalizuje zdarzeniu, że się zakończył (Jest to uproszczona wersja mojego kodu, ale kończy się niepowodzeniem w tym samym miejscu)

Ale dzieje się tak, że przez większość czasu główny wątek będzie czekał wiecznie na jeden z WaitOne () pozornie losowo.

Musiałem też skomentować niektóre części mojego kodu, ponieważ doprowadziło to do jeszcze bardziej nieoczekiwanego zachowania (tj. jakoś po zakończeniu każdego wątku główny wątek wskoczyłby z powrotem do klauzuli for i spowodowałby IndexOutOfBounds)

class Threading
{
static Mutex CM;
static List<Manga> SharedList;
static ManualResetEvent CEvent = new ManualResetEvent(false);
static ManualResetEvent Event1 = new ManualResetEvent(false);
static ManualResetEvent Event2 = new ManualResetEvent(false);
static ManualResetEvent Event3 = new ManualResetEvent(false);
static ManualResetEvent Event4 = new ManualResetEvent(false);

public List<Manga> ThreadedMangaIndexCrawl(int MaxThreads)
{
CM = new Mutex(false);
SharedList = new List<Manga>();

ManualResetEvent[] evs = new ManualResetEvent[4];
evs[0] = Event1;    // Event for t1
evs[1] = Event2;    // Event for t2
evs[2] = Event3;    // Event for t3
evs[3] = Event4;    // Event for t4

/*for (int i = 0; i < MaxThreads + 1; i++)
{
if (i > MaxThreads)
{ break; }
Thread t = new Thread(() => this.StartIndexCrawling(1,i,i+1,evs[i]));
t.Start();
}*/
int i = 0;
Thread t1 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i]));
t1.Name = "Thread" + i;
t1.Start();
i++;
Thread t2 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i]));
t2.Name = "Thread" + i;
t2.Start();
i++;
Thread t3 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i]));
t3.Name = "Thread" + i;
t3.Start();
i++;
Thread t4 = new Thread(() => this.StartIndexCrawling(1, i, i + 1, evs[i]));
t4.Name = "Thread" + i;
t4.Start();


/* foreach (var e in evs)
{
e.WaitOne();

}*/

evs[0].WaitOne();
evs[1].WaitOne();
evs[2].WaitOne();
evs[3].WaitOne();

return SharedList;
}

void StartIndexCrawling(int Target, int Start, int End, ManualResetEvent E)
{
Thread.Sleep(1000);
CM.WaitOne();
CM.ReleaseMutex();
E.Set();
}
}

Każda pomoc byłaby świetna

Odpowiedzi:

7 dla odpowiedzi № 1

Najprawdopodobniej wszystkie cztery wątki zostaną wykonane:

this.StartIndexCrawling(1, 3, 3 + 1, evs[4]);

Ma to związek z korzystaniem z zamknięć. Wszystkie cztery wątki zostaną powiązane ze zmienną i i użyj dowolnej wartości, jaką ma po wykonaniu kodu (a nie wartości, gdy Thread obiekt zostanie utworzony).

Twój kod prawdopodobnie nie zadziała, jeśli wszystkie cztery wątki będą miały tę samą wartość.


0 dla odpowiedzi nr 2

Zobacz odpowiedź Codo.
Oto, co powinieneś zrobić, aby to rozwiązać:

   int i = 0;
Thread t1 = new Thread(() => this.StartIndexCrawling(1, 0, 1, Event1));
t1.Name = "Thread" + i;
t1.Start();
i++;
Thread t2 = new Thread(() => this.StartIndexCrawling(1, 1, 2, Event2));
t2.Name = "Thread" + i;
t2.Start();
i++;
Thread t3 = new Thread(() => this.StartIndexCrawling(1, 2, 3, Event3));
t3.Name = "Thread" + i;
t3.Start();
i++;
Thread t4 = new Thread(() => this.StartIndexCrawling(1, 3, 4, Event4));
t4.Name = "Thread" + i;
t4.Start();