2

我有 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 语句,它将在单键按下时运行所有视频。但我想运行线程所在的特定视频..

请帮帮我

4

3 回答 3

5

ThreadState 是位掩码类型的属性(enum 有 [Flags] 属性,总是提示),所以不用==直接检查,只需要检查相关位即可:

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

阅读此处了解 ThreadState 值的含义。通过阅读它,可能还有整篇文章或整本书(强烈推荐!),您也很可能会注意到您的方法可能不是理想的方法。虽然不知道你的确切结局,但很难建议一个确切的结局。

于 2012-09-12T08:01:21.923 回答
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该类,您甚至可能想要创建该类的 theThreadstringvalues 字段。您甚至可能希望在您的按钮上创建一个新对象类型的字段,以便每个按钮都与一个按钮相关联。这在面向对象设计中更为典型。没有理由你应该维护四个独立的大小相同的数组,每个数组都有不同的类型。

于 2012-09-12T08:31:50.963 回答
0

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

这来自ThreadState以一种可疑的奇怪方式实现的事实:通常,位掩码状态是使用例如 bit 1 来实现 stateon和相同的 bit 来实现的off。事实并非如此,例如,Running 状态具有 0 值,而 1 值被StopRequested.

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

第一种方法是使用 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();
于 2021-05-31T08:40:18.747 回答