C# 错误:非静态字段需要对象引用

本文关键字:对象引用 字段 静态 错误 | 更新日期: 2023-09-27 18:37:18

我有一个小的Windows表单程序,它使用console.beep从字符串播放音乐。我在一个新的线程"t"中设置了字符串播放位(它基本上是一个 for 循环,通过字符串 char 一个字符并播放适当的音符)。当您点击"播放"按钮时,线程启动,按钮变为"停止"按钮。如果您在播放音乐时点击此"停止"按钮,它将停止并且按钮将变回播放(通过调用"完成"方法。我的问题是,我希望在新线程中运行的循环在循环运行并且歌曲结束时也调用"完成"方法。但是如果我在循环之后放置 finish(),我会得到"非静态字段需要对象引用"错误。如果我将"finshed"方法更改为静态,那么更改按钮文本的位将不起作用......

这是按下按钮时的代码...

//This is the method for when the "start" button is clicked
public void button1_Click(object sender, EventArgs e) 
    {
        if (music == null) { return; }
        if (button1.Text == "Play")
        {
            // it makes a new thread which calls my "parse" method which 
            // interprets the music and then calls "playnote" to play it.
            Thread t = new Thread(parse); 
            t.Start();
            button1.Text = "Stop";
        }
        else 
        {
            finished();
        }
    }
    public void finished()
    {
        stop = true;
        button1.Text = "Play";
    }

有什么建议吗?

提前非常感谢!

编辑:谢谢大家!!我真的没有时间弄清楚后台工作人员 atm,所以我现在只有单独的开始和停止按钮!:p

C# 错误:非静态字段需要对象引用

我认为使用BackgroundWorker 线程可以更好地完成此操作。这样,您就可以在RunWorkerCompleted事件中调用 finished() 方法。

parse() 方法是静态的吗?似乎您正在尝试从静态方法调用 done() 而不提供实例,这就是您收到"非静态字段需要对象引用"错误的原因。

您需要

做的是确保创建的线程可以访问创建它的对象(即"this",在您的"button1_Click()"方法的范围内)。为此,您可以调用 t.Start(this) 而不是 t.Start()。这样做,您将向线程传递能够调用"finish()"方法的对象。接下来,您需要确保"parse"方法采用 Object 类型的参数。这样做时,当您调用"t.Start(this)"时,方法"parse"将接收"this"作为参数。需要简单的强制转换才能转换为适当的类型。现在,当您希望在线程中停止歌曲时,只需在强制转换参数上调用"finish()"方法即可。因此,您的代码应如下所示:

公共无效解析(对象 O){ MyClass c = o as MyClass;将 MyClass 替换为您的类的名称

[...] // play music here
c.finished();  // call finished when you are done

}

public void button1_Click(Object sender, EventArgs e){ [...]

线程 t = 新线程(解析); t.开始(这个);而不是 t.Start()

[...]}

静态与成员方法

  1. 要么你有一个成员(非静态)方法,你调用它
obj.SomeMethod();
  1. 或者你有一个静态方法,你调用它
ClassName.SomeMethod();

除非它在定义类本身内部调用。然后可以简单地调用它

SomeMethod();

在这两种情况下。


线程

唯一允许与UI交互(例如与button1.Text)交互的线程是UI线程本身。UI 线程是代码正常运行的主线程。

请参阅如何在 C# 中从另一个线程更新 GUI?,以便与另一个线程中的窗体进行交互。

你需要做的是在主线程上引发一个事件来调用你完成的方法。首先在窗体类中声明事件和委托。

public delegate void CallFinishedEventHandler();
public event CallFinishedEventHandler CallFinished;

然后创建一个事件处理程序,该处理程序将在引发事件时调用,并在 调用已完成的方法。

void Form1_CallFinished()
{
  Finished();
}

然后在窗体构造函数中将事件处理程序连接到事件。

public Form1()
{
    CallFinished += Form1_CallFinished;
}
最后,在

音乐播放代码中,当您想要调用已完成的方法(在 UI 线程上)时,请调用您的事件,以便在 UI 线程上触发它。

this.Invoke(CallFinished);

这很简单,创建一个全局线程,然后在您想要的位置访问它。

Thread t;
    public void button1_Click(object sender, EventArgs e) 
        {
            if (music == null) { return; }
            if (button1.Text == "Play")
            {
                // it makes a new thread which calls my "parse" method which 
                // interprets the music and then calls "playnote" to play it.
                t = new Thread(parse); 
                t.Start();
                button1.Text = "Stop";
            }
            else 
            {
                finished();
            }
        }
        public void finished()
        {
            stop = true;
            button1.Text = "Play";
        }

对于调用 finish,创建窗体类的实例,然后调用该方法。

Form1 frm1 = new Form1();
frm1.finished();