如何检查线程的状态

时间:2012-09-12 07:12:37

标签: c# .net multithreading

我有winform应用程序,我正在尝试播放多个视频,我正在为此创建线程。我的代码是:

public String[,] vpath = new String[3, 7]; 
public Video[,] video = new Video[3, 7];
public static Thread[,] th = new Thread[3, 7];

public void playclick(object sender, EventArgs e)
    {
        int i, j;

        for (j = 0; j <= 7 - 1; j++)
        {
            for (i = 0; i <= 3 - 1; i++)
            {
                if (btnp[i, j].Capture)
                {
                    //play();

                    th[i, j] = new Thread(new ThreadStart(play));
                    th[i, j].IsBackground = true;
                    th[i, j].Start();
                }
            }
        }

    }

 public void play()
    {

            int i, j;
            for (j = 0; j <= 7 - 1; j++)
            {
                for (i = 0; i <= 3 - 1; i++)
                {
                    if (th[i, j].ThreadState == ThreadState.Running) // Having problem here
                    {
                        if (video[i, j].State != StateFlags.Running)
                        {
                            video[i, j].Play();
                        }
                    }
                }
            }      
    }

因此,如果没有if语句,它将按下单按钮上的所有视频。但我想运行线程所在的特定视频..

请帮助我们

3 个答案:

答案 0 :(得分:4)

ThreadState是一个bitmask类型的属性(enum有[Flags]属性,它始终是提示),所以你不要使用==直接检查它,你只需要检查相关位:

if ((t.ThreadState & ThreadState.Running) == ThreadState.Running) { ...

阅读here有关ThreadState值的含义。从阅读那篇文章,或者整篇文章,或整本书(强烈推荐!),你也很可能会注意到你的可能不是理想的方法。 虽然不知道你的确切结局,但很难建议一个确切的结局。

答案 1 :(得分:1)

至于为什么你得到一个例外,HaemEternal在他的评论中指出了这一点。您只是一次初始化一个线程,但是您正在检查所有线程。 null线程对象没有ThreadState值。

我可以建议你完全改变你的设计; 无需经常检查哪个线程被激活。您可以更改Play()方法的签名以接受Object,然后您可以使用Object将正确的视频传递给该方法。

public void playclick(object sender, EventArgs e)
{
    int i, j;

    for (j = 0; j <= 7 - 1; j++)
    {
        for (i = 0; i <= 3 - 1; i++)
        {
            if (btnp[i, j].Capture)
            {
                //play();

                th[i, j] = new Thread(new ParameterizedThreadStart(play));
                th[i, j].IsBackground = true;
                th[i, j].Start(video[i,j]);
            }
        }
    }

}

public void play(object video)
{
    Video vid = video as Video; 
    if (vid.State != StateFlags.Running)
    {
        vid.Play();
    }        
}

更好的方法是将这三个元素封装在一个包含Video对象,Thread对象和路径string的对象中。

如果您拥有Video课程,您甚至可能想要制作该课程的Threadstring值字段。 您甚至可能希望在这个新对象的类型按钮上创建一个字段,因此每个按钮都会与一个按钮相关联。 这是面向对象设计的典型特征。没有理由你应该维护四个相同大小的数组,每个数组都有不同的类型。

答案 2 :(得分:0)

@tar 的回答给出了一些提示,但代码是错误的(如@Sampath 所评论)。

这是因为 ThreadState 以一种可疑的奇怪方式实现: 通常位掩码状态使用例如状态 on 的位 1 和 相反 off 的相同位。事实并非如此,事实上,例如,Running state 的值为 0,而 StopRequested 取值为 1。

所以做一点检查是不明智的。

第一种方法是使用 or 语句检查状态:

while (t.ThreadState == ThreadState.Running ||
    t.ThreadState == ThreadState.Background)
    Application.DoEvents();
t.Join();

请记住,如果您在后台启动进程,您将拥有 ThreadState.Background 枚举值返回而不是 ThreadState.Running, 这就是为什么我把两者都放了。

更好、更简单的方法是:

while (t.IsAlive)
    Application.DoEvents();
t.Join();