使用C#中的参数调用方法的最短方法

时间:2016-01-19 08:53:54

标签: c#

当我需要在指定的线程中调用一些代码时,我使用的是这样的东西:

Dispatcher dispatcher = Dispatcher.CurrentDispatcher;

delegate void MethodToInvokeDelegate(string foo, int bar);

void MethodToInvoke(string foo, int bar)
{
    DoSomeWork(foo);
    DoMoreWork(bar); 
}

void SomeMethod()
{
    string S = "Some text";
    int I = 1;
    dispatcher.BeginInvoke(new MethodToInvokeDelegate(MethodToInvoke), new object[] {S, I});
}

此代码工作正常,但它很重。我想在不声明MethodToInvokeMethodToInvokeDelegate的情况下使用匿名方法制作它。但我无法弄清楚如何将参数传递给它。

我不能这样写:

dispatcher.BeginInvoke((Action)delegate() { DoSomeWork(S); DoMoreWork(I); });

我需要将参数传递给方法。

是否可以简单易懂?

示例:

Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
int[] ArrayToFill = new int[3];

void SomeMethod()
{
    for (int i = 0; i < 3; i++)
        dispatcher.BeginInvoke( { ArrayToFill[i] = 10; } );
}

此代码不起作用:将使用i = 1,2,3调用方法,并将引发IndexOutOfRange异常。在方法开始执行之前,i将递增。所以我们需要重写它:

Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
int[] ArrayToFill = new int[3];

delegate void MethodToInvokeDelegate(int i);

void MethodToInvoke(int i)
{
    ArrayToFill[i] = 10; 
}

void SomeMethod()
{
    for (int i = 0; i < 3; i++)
         dispatcher.BeginInvoke(new MethodToInvokeDelegate(MethodToInvoke), new object[] {i});
}

3 个答案:

答案 0 :(得分:3)

如果您希望避免为每次通话创建委托类型,请使用Action<>Action<,>

Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
string S = "Some text";
int I = 1;
dispatcher.BeginInvoke(
                        (Action<string, int>)((foo, bar) =>
                        {
                            MessageBox.Show(bar.ToString(), foo);
                            //DoSomeWork(foo);
                            //DoMoreWork(bar); 
                        }), 
                        new object[] { S, I }
                      );

ArrayToFill[j] = 10;动作的示例可以很简单地修复:

for (int i = 0; i < 3; i++)
{
    int j = i;
    // lambda captures int variable
    // use a new variable j for each lambda to avoid exceptions
    dispatcher.BeginInvoke(new Action(() =>
    {
        ArrayToFill[j] = 10;
    }));
}

答案 1 :(得分:0)

试试这个:

string S = "Some text";
int I = 1;

dispatcher.BeginInvoke(new Action(() =>
{
    DoSomeWork(S);
    DoMoreWork(I);
}));

[编辑]

回答您修改过的问题:

您看到的问题是modified closure problem

要修复它,您只需要在调用方法之前复制参数:

Dispatcher dispatcher = Dispatcher.CurrentDispatcher;

int[] ArrayToFill = new int[3];

for (int i = 0; i < 3; i++)
{
    int index = i;
    dispatcher.BeginInvoke(new Action(() => { ArrayToFill[index] = 10; } ));
}

答案 2 :(得分:0)

yourUIcontrol.BeginInvoke(new MethodInvoker(delegate {
    //your code goes here
}));