簡體   English   中英

.NET-有什么方法可以創建非靜態線程方法?

[英].NET - Is there any way to create a non-static thread method?

有什么方法可以在.NET上創建非靜態線程方法? 請告訴我代碼。

以下代碼不起作用:

ThreadStart ts = delegate { drawFloorAround(); };
public void drawFloorAround()
{
            ...
}

給出此錯誤->“字段初始化器無法引用非靜態字段,方法或屬性”。 如果我更改方法做靜態,它的工作原理。 但是我不想。

...給出此錯誤“字段初始化器無法引用非靜態字段,方法或屬性”。

仔細閱讀錯誤消息。 它准確地告訴您出了什么問題。 字段初始化程序不能引用非靜態方法 這是因為編譯器試圖保護您免受此錯誤的影響:

class C
{
    int foo;
    int bar = GetBar();
    public C(int newFoo)
    {
        this.foo = newFoo;
    }
    private int GetBar() { return this.foo + 1; }
}

您執行“新C(123)”。 欄設置為什么? 如果這是合法代碼,則將其設置為1,而不是124。為什么? 因為首先將foo初始化為零,然后調用GetBar(),然后構造函數主體將this.foo設置為123。

為防止此錯誤,在字段初始化器中引用實例方法或字段完全是非法的。

現在,您可能會合理地指出,在您的代碼中,您沒有使用實例方法,而只是引用了它。 您從未真正稱呼它。 這實際上是安全的。 但是,C#的規則設計得既簡單又保守。 即使我們可以證明這種情況是安全的,我們還是采取保守,簡單的方法,並說在字段初始化器中對該實例的任何引用都是非法的。

如果我將方法更改為靜態,則可以使用。

正確。 在那種情況下,該方法不依賴於尚未建立的實例狀態。

但是我不想。

好的,那么您唯一的選擇是停止使用字段初始化器 將初始化放入構造函數中; 然后,您有責任確保初始化不會意外使用未初始化狀態。

如果您的意思是可以使用非靜態方法 (即實例方法) 啟動線程,則可以。 但是,與直接調用實例方法相同的規則適用-您只有在擁有實例的情況下才可以執行。 例如,如果您在名為foo的變量中有一個實例,則可以這樣編寫:

ThreadStart ts = delegate { foo.DrawFloorAround(); };

如果還沒有可以使用的實例,則必須首先創建一個實例:

ThreadStart ts = delegate { new Foo().DrawFloorAround(); };

如果您不想創建實例,那么您的方法可能應該是靜態的。

    public class DoSomthing
    {

        public void Do()
        {
            Thread t = new Thread(DoInBackground);
            t.Start();
        }

        public void DoInBackground()
        {
            // ....
        }

    }

編輯:示例代碼中的問題是它是一個字段初始化程序。 將此代碼移至顯式構造函數:

ThreadStart ts;
public TypeName() {//constructor
    ts = this.SomeMethod;
}
private void SomeMethod() {....}

任何方法都可以充當ThreadStart作為日志廣告,它不占用任何參數,並且返回void。 IMO最簡單的選擇是lambda或anon方法,因為它允許關閉:

ThreadStart ts = delegate {
    someObj.DoSomething(x, y, "z");
};

但是對於返回void並且不包含參數的實例方法:

var obj = /* init obj */
ThreadStart ts = obj.SomeMethod;

然后

var thread = new Thread(ts);

初始化程序在構造函數之前運行,因此您沒有實例可將其設置為。 在構造函數中設置值,就可以了。

class DoesNotWork {
    public Action ts = Frob; // doesn't work, cannot access non-static method 
    void Frob() { }
}
class ThisIsFine {
    public Action ts;
    public ThisIsFine() { ts = Frob; }
    void Frob();
}

從vb.net轉到C#的任何人都必須注意,規則已在VB.net和C#之間更改,這一點很重要。 在vb.net(更好的IMHO)規則下,初始化程序在對mybase.new的調用與構造函數的以下語句之間運行; 字段初始化程序可以引用當前對象的字段和屬性。 雖然如果不注意會引起問題,但是它允許在源代碼中與聲明相同的位置處處理變量初始化(在某些情況下為清理)。 遷移到C#的任何人都必須認識到初始化程序處理方面的這種區別。 盡管可以在vb.net中正確處理在初始化程序中創建的iDisposable,但在C#中,如果不使用線程靜態變量進行大量操作,這是不可能的。

暫無
暫無

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

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