簡體   English   中英

C#錯誤:非靜態字段需要對象引用

[英]C# error: object reference is required for the non static field

我有一些小窗體程序,使用console.beep從字符串播放音樂。 我有一個字符串播放位(它基本上是一個for循環,通過字符串char char並播放相應的音符)在新線程't'中設置。 當您點擊“播放”按鈕時,線程開始,按鈕變為“停止”按鈕。 如果您在音樂播放時點擊此“停止”按鈕,它將停止並且按鈕變回播放(通過調用“已完成”方法。我的問題是我希望在新線程中運行的循環也調用當循環已經運行並且歌曲結束時,“完成”方法。但是如果我在循環之后放置了完成(),則得到“非靜態字段需要對象引用”錯誤。如果我更改“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

我認為使用BackgroundWorker線程可以更好地完成。 這樣您就可以在RunWorkerCompleted事件中調用finished()方法。

parse()方法是靜態的嗎? 看起來你試圖從靜態方法調用finished()而不提供實例,這就是為什么你得到“非靜態字段需要對象引用”的錯誤。

您需要做的是確保創建的線程可以訪問創建它的對象(即“this”,在“button1_Click()”方法的范圍內)。 為此,您可以調用t.Start(this)而不是t.Start()。 這樣做,您將傳遞給能夠調用“finished()”方法的對象的線程。 接下來,您需要確保“parse”方法采用Object類型的參數。 這樣做時,當你調用“t.Start(this)”時,方法“parse”將接收“this”作為參數。 轉換為適當的類型需要簡單的強制轉換。 現在,當你想要在線程中停止歌曲時,只需在casted參數上調用“finish()”方法。 所以你的代碼應該是這樣的:

public void parse(object 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.Start(本); //而不是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";
        }

要調用finished,請創建表單類的實例,然后調用該方法。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM