C#从线程中调用的函数返回值

C#从线程中调用的函数返回值,c#,multithreading,invoke,value-type,C#,Multithreading,Invoke,Value Type,我有一个计算线程函数,它使用Invoke从其他线程调用消息函数,我希望计算线程从该消息函数中获取值(valuetype,比如integer)。我该怎么做 问题是在调用(…)之后,我仍然会得到x变量的旧值,而我期望值为15 delegate void mes_del(object param); void MyThreadFunc() { ... int x = 5; object [] parms = new object []{x}; Invoke(new mes_del(MessageFu

我有一个计算线程函数,它使用Invoke从其他线程调用消息函数,我希望计算线程从该消息函数中获取值(valuetype,比如integer)。我该怎么做

问题是在调用(…)之后,我仍然会得到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;
}
我尝试了一些方法,比如使用object[],object作为参数,但没有成功。我认为装箱/拆箱操作应该在这种情况下发生,但事实并非如此。 我应该像在.NET事件模式中那样使用辅助类型,而像在.NET事件模式中那样创建中介对象吗 阶级持有者 { 公共int x; }

上面的代码所做的是声明一个局部变量,将其赋值为5,然后构造一个
object[]
数组,其中包含一个作为该局部变量副本的元素

然后将此数组传递到
Invoke
调用中

我想你会发现在调用
Invoke
之后,
parms[0]
是15。但这并不影响
x
,任何方法都必须将其作为
ref
参数传递,才能修改其局部值


我以前看到的是这样的:

class Box<T>
{
    public T Value { get; set; }
}
类框
{
公共T值{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;
}
void MyThreadFunc()
{
var x=新框{Value=5};
//顺便说一下,真的没有理由定义你自己的
//mes_del委托类型。
调用(新操作(MessageFunc),x);
}
void MessageFunc(框参数)
{
参数值=15;
}
上面的代码所做的是声明一个局部变量,将其赋值为5,然后构造一个
object[]
数组,其中包含一个作为该局部变量副本的元素

然后将此数组传递到
Invoke
调用中

我想你会发现在调用
Invoke
之后,
parms[0]
是15。但这并不影响
x
,任何方法都必须将其作为
ref
参数传递,才能修改其局部值


我以前看到的是这样的:

class Box<T>
{
    public T Value { get; set; }
}
类框
{
公共T值{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;
}
void MyThreadFunc()
{
var x=新框{Value=5};
//顺便说一下,真的没有理由定义你自己的
//mes_del委托类型。
调用(新操作(MessageFunc),x);
}
void MessageFunc(框参数)
{
参数值=15;
}

您是说从Windows窗体调用
控件吗?如果是,该方法还可以返回结果,因此您可以编写:

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
,而不是从数组中选择一个新值(应该修改)。但是,使用返回新值的重载应该是更清晰的解决方案

您是说从Windows窗体调用控件吗?如果是,该方法还可以返回结果,因此您可以编写:

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
,而不是从数组中选择一个新值(应该修改)。但是,使用返回新值的重载应该是更清晰的解决方案

仅从方法返回值

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;
}
void MyThreadFunc()
{
...
int x=5;
object[]parms=新对象[]{x};
var callResult=(int)Invoke((Func)MessageFunc,(object)parms);
...
}
int MessageFunc(对象结果)
{
int res=15;
返回res;
}

只需从方法返回值

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;
}
void MyThreadFunc()
{
...
int x=5;
object[]parms=新对象[]{x};
var callResult=(int)Invoke((Func)MessageFunc,(object)parms);
...
}
int MessageFunc(对象结果)
{
int res=15;
返回res;
}

对于您的问题,最好的答案可能是在.NET 4.0中

在这里,主线程被阻塞,直到另一个线程上调用的方法返回结果。如果主线程已经返回结果并到达WriteLine,则没有阻塞

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

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


也许对你的问题最好的答案是在.NET 4.0中

在这里,主线程被阻塞,直到另一个线程上调用的方法返回结果。如果主线程已经返回结果并到达WriteLine,则没有阻塞

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

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


给我们多一点代码。在代码中调用
Invoke
之后会发生什么?
MessageFunc
正在正确地更改值,因此您没有等待异步任务完成,或者您获取修改值的代码不正确。@Jim:它没有更改
x
的值@丹涛:当然它不会改变
x
的值@吉姆:OP说,“问题是我在调用(…)之后仍然得到x变量的旧值”;您的评论听起来像是在暗示问题与等待异步调用有关,而实际上OP的当前代码永远不会更改
x
的值。另外,假设OP使用的是Windows窗体,
Control.Invoke
会自动等待UI执行代码(而不是
Control.BeginInvoke
,后者不会执行)。@Dan Tao:我想我给了比预期更多的信任。我没有想到OP期望自动地改变代码> x>代码>。我想他知道他必须从数组中获取新值
x
。是的,我把
Invoke
理解为
BeginInvoke
。给我们多一点代码。在代码中调用
Invoke
之后会发生什么?
MessageFunc
正在正确地更改值,因此您没有等待异步任务完成,或者您获取修改值的代码不正确。@Jim:它没有更改
x
的值@丹涛:当然它不会改变
x
的值@吉姆:OP说,“问题是我