2011-03-03 36 views
0

我有一個計算線程函數,它使用Invoke從其他線程調用消息函數,我希望計算線程從該消息函數中獲取value(value的類型,如整數)。我怎樣才能做到這一點?C#線程中調用函數的返回值

的問題是,我的invoke(...)後,仍然得到變量x的原值和我預計的15

delegate void mes_del(object param); 

void MyThreadFunc() 
{ 
... 
int x = 5; 
object [] parms = new object []{x}; 
Invoke(new mes_del(MessageFunc), (object)parms); 
... 
} 

void MessageFunc(object result) 
{ 
    int res = 15; 
    (result as object[])[0] = res; 
} 

值我試着像使用對象[],對象與參數的一些方法沒有成功。我雖然拳擊/拆箱操作應該發生在這種情況下,但他們沒有。 我應該像使用.NET事件模式一樣使用輔助類型並創建中介對象,如 類持有者 public int x; }

+0

給我們多一點的代碼。在你的代碼中調用'Invoke'之後會發生什麼? 'MessageFunc'正確地更改了值,所以要麼不等待異步任務完成,要麼代碼獲取修改後的值不正確。 – 2011-03-03 15:43:49

+0

@Jim:它不會改變'x'的值! – 2011-03-03 16:09:16

+0

@丹濤:當然不會改變'x'的價值! – 2011-03-03 19:35:20

回答

4
int x = 5; 
object [] parms = new object []{x}; 

什麼上面的代碼的作用是聲明一個局部變量,分配給它的值5,然後構造一個object[]數組包含一個元素它是局部變量的副本

然後您將此數組傳遞給您的Invoke調用。

我想你會發現,Invoke被調用後,parms[0]是15但這並不影響x,這實際上將要傳遞的ref參數任何方法能夠修改其當地價值。


我所看到之前完成是這樣的:

class Box<T> 
{ 
    public T Value { get; set; } 
} 

然後,你可以這樣做:

void MyThreadFunc() 
{ 
    var x = new Box<int> { Value = 5 }; 

    // By the way, there's really no reason to define your own 
    // mes_del delegate type. 
    Invoke(new Action<Box<int>>(MessageFunc), x); 
} 

void MessageFunc(Box<int> arg) 
{ 
    arg.Value = 15; 
} 
+0

Just Fyi:['StrongBox '](http://msdn.microsoft.com/en-us/library/bb549038.aspx)class – Ani 2011-03-03 15:52:05

+0

@Ani:是的,我真的注意到了。但是這讓我感到緊張:「這個API支持.NET Framework基礎結構,並不打算直接從你的代碼中使用。」幾乎聽起來像他們保留剛剛擺脫那個班的權利。 (另外,它在一個相當晦澀的命名空間中。) – 2011-03-03 15:56:40

1

你是從Windows窗體談論Control.Invoke?如果是,該方法還可以返回結果,所以你可以寫:

delegate int mes_del(int param); 

void MyThreadFunc() { 
    int x = 5; 
    object [] parms = new object []{x}; 
    x = (int)Invoke(new mes_del(MessageFunc), x); 
    // you'll get a new value of 'x' here (incremented by 10) 
} 

int MessageFunc(int result) { 
    return result + 10; 
} 

您的代碼可能沒有工作,因爲你在訪問x而不是從陣列選擇一個新的值(即應修改)。但是,使用返回新值的重載應該是更清晰的解決方案。

0

剛剛從方法的返回值

void MyThreadFunc() 
{ 
... 
int x = 5; 
object [] parms = new object []{x}; 
var callResult = (int)Invoke((Func<object,int>)MessageFunc, (object)parms); 
... 
} 

int MessageFunc(object result) 
{ 
    int res = 15; 
    return res; 
} 
+0

你的例子不會編譯。 'mes_del'委託類型返回'void',所以'new mes_del(MessageFunc)'會給出一個錯誤,即MessageFunc具有錯誤的返回類型。 – 2011-03-04 14:36:44

0

也許最好的回答你的問題是在.NET 4.0中System.Threading.Tasks

這裏主要線程被阻塞,直到結果是通過呼籲該方法返回其他線程。如果主線程已經返回結果到達WriteLine,則不會阻塞。

Task task = Task.Factory.StartNew(SomeMethod); 
Console.WriteLine(task.Result); 

public static string SomeMethod() 
{ 
    return "Hello World"; 
} 

OR

Task task = Task.Factory.StartNew(() => { return "Hello World"; }); 
Console.WriteLine(task.Result); 

Check this blog for more interesting samples.