微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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.jb51.cc/csharp/243344.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐