Я новичок в потоках, и мне было интересно, как их использовать для оценки в недетерминированном конечном автомате.
У меня есть метод, который вызывает другой метод:
public bool Evaluate2(string s)
{
accepted = false;
ThreadEval(s, StartState);
return accepted;
}
переменная accepted
является членом класса, и я использую ее, чтобы контролировать, когда другие потоки должны останавливаться.
void ThreadEval(string s, State q)
{
if (s.Length == 0 && q.IsFinal)
{
accepted = true;
return;
}
bool found = true;
State current = q;
for (int i = 0; found && !accepted && i < s.Length; i++)
{
found = false;
foreach (Transition t in current.transitions)
if (t.symbol == s[i])
{
Thread thread = new Thread(new ThreadStart(delegate { ThreadEval(s.Substring(i+1), t.to); }));
thread.Start();
found = true;
}
}
}
Каждое из моих состояний имеет набор переходов. Переход состоит из символа и состояния, в которое он может перейти, потребляя этот символ. Поэтому всякий раз, когда я нахожу возможный переход, я хочу создать новый поток и изучить остальную часть строки (без текущего символа)...
У меня сейчас 2 проблемы:
«Возврат принят» выполняется до того, как все потоки, созданные внутри ThreadEval, закончат их. Есть ли способ гарантировать, что он не вернется, пока эти потоки не закончатся? Я поставил Thread.Sleep(200) перед возвратом, и это сработало, но 200 мс может быть недостаточно для больших строк, и я также не хочу повышать значение, поэтому маленькие строки будут обрабатываться дольше, чем должны. .
Код в том виде, в котором он есть, приводил к некоторому исключению индексации... Я на 99,999% уверен, что он правильный, но он предотвратит сбой, только если я вызову подстроку, передающую значение i вместо i + 1... но если я вызову только i, он никогда не дойдет до конца строки и, в зависимости от конфигурации автомата, может привести к бесконечности петля. Я точно не знаю, как работают потоки, но подозреваю, что, возможно, какая-то параллельная обработка изменяет значение i перед нарезкой подстроки. Как я могу гарантировать, что всякий раз, когда я вызываю новый поток, я отбрасываю только текущий символ?
Если у кого-то есть какие-либо предложения о том, как использовать потоки с большей элегантностью, я был бы признателен, пока единственный способ передать параметры в функцию, которой был назначен поток, - это использовать делегат.