【问题标题】:C# error: object reference is required for the non static fieldC# 错误:非静态字段需要对象引用
【发布时间】:2012-06-14 18:22:15
【问题描述】:

我有一个小的 Windows 窗体程序,它使用 console.beep 从字符串中播放音乐。我在一个新线程't'中设置了字符串播放位(基本上是一个for循环,逐个字符地遍历字符串并播放适当的音符)。当您点击“播放”按钮时,线程启动并且按钮变为“停止”按钮。如果您在播放音乐时点击这个“停止”按钮,它将停止并且按钮变回播放(通过调用“完成”方法。 我的问题是我希望在新线程中运行的循环在循环运行并且歌曲结束时也调用“完成”方法。 但是,如果我在循环之后放置finished(),我会得到“非静态字段需要对象引用”错误。如果我将“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# multithreading visual-studio-2010 static


    【解决方案1】:

    我认为这会更好地完成with a BackgroundWorker thread。这样您就可以在RunWorkerCompleted 事件中调用finished() 方法。

    【讨论】:

      【解决方案2】:

      parse() 方法是静态的吗?似乎您试图在不提供实例的情况下从静态方法调用finished(),这就是为什么您会收到“非静态字段需要对象引用”错误。

      【讨论】:

        【解决方案3】:

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

        公共无效解析(对象o) { 我的班级 c = o 作为我的班级; // 用你的类名替换 MyClass

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

        }

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

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

        [...] }

        【讨论】:

          【解决方案4】:

          静态与成员方法

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

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

          SomeMethod();
          

          在这两种情况下。


          线程

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

          请参阅 How to update the GUI from another thread in C#? 以从另一个线程与表单交互。

          【讨论】:

            【解决方案5】:

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

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

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

            void Form1_CallFinished()
            {
              Finished();
            }
            

            然后在您的表单构造函数中将您的事件处理程序连接到您的事件。

            public Form1()
            {
                CallFinished += Form1_CallFinished;
            }
            

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

            this.Invoke(CallFinished);
            

            【讨论】:

              【解决方案6】:

              这很简单,创建一个全局线程,然后在你想要的地方访问它。

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

              【讨论】:

                【解决方案7】:

                为了调用完成,创建一个表单类的实例,然后调用该方法。

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

                【讨论】:

                • -1:OP 需要在同一个 Form1 实例上调用 finished
                • 在这样做之后(我把它放在我的“解析”方法中的 for 循环之后)它编译并运行没有错误,但似乎没有调用“完成”方法。 IE。按钮文本不会改变
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-05-03
                相关资源
                最近更新 更多