c# – 暂停一个线程直到一个方法和所有内部线程完成他们的工作?

前端之家收集整理的这篇文章主要介绍了c# – 暂停一个线程直到一个方法和所有内部线程完成他们的工作?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我是线程的新手,我想知道如何使用它们在非确定性有限自动机中进行评估.

我有调用另一个方法方法

public bool Evaluate2(string s)
{
    accepted = false;

    ThreadEval(s,StartState);            

    return 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;
            }
     }
}

我的每个州都有一组过渡.转换由符号和消耗该符号的状态组成.因此,每当找到可能的转换时,我想创建一个新线程并检查字符串的其余部分(没有当前字符)…

我目前遇到两个问题:

>在ThreadEval内创建的所有线程完成之前,正在执行“return accepted”.有没有办法确保它不会返回,直到那些线程结束?
我在返回之前放了一个Thread.Sleep(200)并且它工作但是对于大字符串来说200 ms可能还不够,我也不想提高值,所以小字符串需要的时间比应该处理的要长.
>代码的方式是导致一些索引异常…我99.999%确定它是正确的,但它只会停止崩溃,如果我调用子串传递值i而不是i 1. ..但如果我只用i调用它将永远不会到达字符串的末尾,并且取决于自动机配置可能导致无限循环.我不确切地知道线程是如何工作的,但我怀疑可能有些并行处理在子串切片之前改变了i的值.
我怎么能保证每当我调用一个新线程时我只丢弃当前的char?

如果有人对如何使用更优雅的线程有任何建议,我将不胜感激,到目前为止,我发现在线程分配的函数中传递参数的唯一方法是使用委托.

解决方法

为了阻塞直到线程t执行完成,您可以使用Thread.Join.
t.Join();

这将主线程置于IDLE状态,直到线程t完成.
这意味着你必须跟踪在foreach循环中创建的所有线程,然后逐个连接它们.

更好的方法是使用TPL的任务< T>而不是直接使用线程.你的代码有点像这样:

Task ThreadEval(string s,State q)
{
    //...

    List<Task> tasks = new List<Task>();

    for (int i = 0; found && !accepted && i < s.Length; i++)
    {
        found = false;
        foreach (Transition t in current.transitions)
            if (t.symbol == s[i])
            {
                tasks.Add(
                    Task.Run(
                        () => await ThreadEval(s.Substring(i+1),t.to)));
                found = true;
            }
     }

    return Task.WhenAll(tasks);
}

await ThreadEval(...);

>更改签名以返回Task而不是void
>创建所有正在运行的任务的列表
> Task.WhenAll将创建一个新任务,当任务列表中的所有任务都标记为完成时,该任务将被标记为完成.返回此任务.

然后调用者将等待ThreadEval.

原文链接:https://www.f2er.com/csharp/243344.html

猜你在找的C#相关文章