c# 예제 - Invoke 호출의 익명 메소드




무명메서드 대리자 (7)

우리가 Control.Invoke 내에서 익명으로 대리자를 호출하려는 구문에 약간의 문제가 있습니다.

우리는 여러 가지 접근법을 시도했지만 모두 쓸모가 없습니다.

예 :

myControl.Invoke(delegate() { MyMethod(this, new MyEventArgs(someParameter)); }); 

someParameter가이 메소드에 대해 로컬 인 경우

위의 경우 컴파일러 오류가 발생합니다.

익명 메서드를 대리자 형식이 아니기 때문에 'System.Delegate'형식으로 변환 할 수 없습니다.


Answers

완전을 기하기 위해 이것은 Action 메소드 / 익명 메소드 조합을 통해 수행 할 수도 있습니다.

//Process is a method, invoked as a method group
Dispatcher.Current.BeginInvoke((Action) Process);
//or use an anonymous method
Dispatcher.Current.BeginInvoke((Action)delegate => {
  SomeFunc();
  SomeOtherFunc();
});

필자는 컴파일러의 차이점을 이해하지 못했지만 이것이 충분합니다.

public static class ControlExtensions
{
    public static void Invoke(this Control control, Action action)
    {
        control.Invoke(action);
    }
}

보너스 : 백그라운드 스레드에서 Control.Invoke 를 사용하는 경우 Control.Invoke 의 텍스트 / 진행 / 사용 가능 상태를 업데이트하고 컨트롤이 이미 삭제되었는지는 상관하지 않으므로 오류 처리를 추가하십시오.

public static class ControlExtensions
{
    public static void Invoke(this Control control, Action action)
    {
        try
        {
            if (!control.IsDisposed) control.Invoke(action);
        }
        catch (ObjectDisposedException) { }
    }
}

사실 대리자 키워드를 사용할 필요가 없습니다. 그냥 매개 변수로 람다 전달 :

control.Invoke((MethodInvoker)(() => {this.Text = "Hi"; }));

Invoke / BeginInvoke 는 (형식화 된 대리자가 아닌) Delegate 허용하므로 컴파일러에 어떤 형식의 대리자를 만들지 알려줄 필요가 있습니다. MethodInvoker (2.0) 또는 Action (3.5)은 일반적인 선택입니다 (동일한 서명이 있음에 유의하십시오). 이렇게 :

control.Invoke((MethodInvoker) delegate {this.Text = "Hi";});

매개 변수를 전달해야하는 경우 "캡처 된 변수"가 그 방법입니다.

string message = "Hi";
control.Invoke((MethodInvoker) delegate {this.Text = message;});

(경고 : 캡쳐 비동기를 사용한다면 신중해야하지만 동기화 는 괜찮습니다.

또 다른 옵션은 확장 메소드를 작성하는 것입니다.

public static void Invoke(this Control control, Action action)
{
    control.Invoke((Delegate)action);
}

그때:

this.Invoke(delegate { this.Text = "hi"; });
// or since we are using C# 3.0
this.Invoke(() => { this.Text = "hi"; });

물론 BeginInvoke 하여 동일한 작업을 수행 할 수 있습니다.

public static void BeginInvoke(this Control control, Action action)
{
    control.BeginInvoke((Delegate)action);
}

C # 3.0을 사용할 수 없으면 Form 기본 클래스에서 정규 인스턴스 메서드를 사용하여 동일한 작업을 수행 할 수 있습니다.


나는 때때로 내 메서드에서 값을 반환하기 때문에 다른 제안에 문제가있었습니다. 반환 값으로 MethodInvoker를 사용하려고 시도하면 MethodInvoker가 마음에 들지 않습니다. 그래서 내가 사용하는 솔루션이 (이게 더 간결하게 만드는 방법을 듣게되어서 기쁩니다 - 저는 C # .net 2.0을 사용하고 있습니다) :

    // Create delegates for the different return types needed.
    private delegate void VoidDelegate();
    private delegate Boolean ReturnBooleanDelegate();
    private delegate Hashtable ReturnHashtableDelegate();

    // Now use the delegates and the delegate() keyword to create 
    // an anonymous method as required

    // Here a case where there's no value returned:
    public void SetTitle(string title)
    {
        myWindow.Invoke(new VoidDelegate(delegate()
        {
            myWindow.Text = title;
        }));
    }

    // Here's an example of a value being returned
    public Hashtable CurrentlyLoadedDocs()
    {
        return (Hashtable)myWindow.Invoke(new ReturnHashtableDelegate(delegate()
        {
            return myWindow.CurrentlyLoadedDocs;
        }));
    }

myControl.Invoke(new MethodInvoker(delegate() {...}))

문제는 대리자 정의와 다르며 Do () 메서드의 매개 변수는 System.Delegate 유형이며 컴파일러에서 생성 한 대리자 형식 (FakeSave)은 암시 적으로 System.Delegate로 변환되지 않습니다.

익명의 대리인 앞에서 캐스트를 추가해보세요.

Expect.Call(delegate { _dao.Save(t); }).Do((Delegate)delegate { t.Message = "I drink goats blood"; });




c# .net compiler-errors anonymous-methods