2011-11-07 3 views
4

사용자 지정 컨트롤이 있고이 컨트롤이 사용자에게 노출되는 인터페이스가 있습니다.비동기 작업 내 주위를 둘러 쌀 필요

public interface ILookupDataProvider 
{ 
    string IdColumnName { get; } 

    IEnumerable<IDataColumn> Metadata { get; set; } 

    void GetDataAsync(string parameters, 
     Action<IEnumerable<object>> onSuccess, Action<Exception> onError); 
} 

그래서, GetDataAsync

에서 비동기 작업을 노출하는 내 시도이다 그러나 나는 인터페이스를 구현하는 내 클래스에서이 메소드를 구현하는 방법을 모르겠어요. 나는이 메소드가 실행되고 나서 onCompletion, onSucess 또는 onError 델리게이트가 호출 됨으로이 부분을 이해합니다.

누군가가이를 작성하는 방법에 대한 구문을 도움이 될 수 있습니까?

편집 :

이 4.0이고 나는 await 명령

편집 2 사용할 수 없습니다 : 내가 데이터를로드 할 수 DevForce 프레임 워크를 사용하지만,이 샘플을 위해

을 - 이제 WCF를하자 예를 들면. 인터페이스 구현시 WCF 서비스 호출을 어떻게 래핑합니까?

또한 비동기 작업을 위해 이와 같은 인터페이스를 만드는 것이 좋다고 생각하십니까? 예를 들어 이벤트와 다르게 할 수 있습니까?

+0

async/await을 사용한 후에 또는 정확히 알고 싶은 것이 있습니까? – flq

+0

대상 : .NET 3.5 또는 .NET 4 –

+0

VS2010을 사용 중이므로 비동기 대기가 불가능합니다.이 인터페이스에 대한 구현을 작성하려고하며 구문을 파악할 수 없습니다. 심지어 비동기가 아닌 간단한 구현으로도 액션 – katit

답변

6

여기서 기본적인 아이디어는 쿼리가 백그라운드 스레드에서 발생한다는 것입니다. 작업이 완료되면 새 값을보고하기 위해 onSuccessonError 콜백을 사용합니다. 당신이 반환되는 Task을 반환에서

Task GetDataAsync(string parameters); 

:

void GetDataAsync(string parameters, 
    Action<IEnumerable<object>> onSuccess, Action<Exception> onError); 

는 대신에, 당신이 사용하고자하는 예를

void GetDataAsync(
    string parameters, 
    Action<IEnumerable<object>> onSuccess, 
    Action<Exception> onError) { 

    WaitCallback doWork = delegate { 
    try { 
     IEnumerable<object> enumerable = GetTheData(parameters); 
     onSuccess(enumerable); 
    } catch (Exception ex) { 
     onError(ex); 
    } 
    }; 

    ThreadPool.QueueUserWorkItem(doWork, null); 
} 
+1

'Task' 또는'Task '이 사용되지 않는 이유를 모르겠다.이 클래스의 전체적인 점은 메소드의 논리 밖에서 비동기 작업 완료 통지를 제어하는 ​​것이다. – casperOne

3

를 들어 당신은 정말이 패턴을 사용하지 않으 비동기 작업 단위를 나타내는 인스턴스 거기에서 API 소비자는 ContinueWith에 전화를 걸어 성공했을 때 또는 오류가있는 경우 수행 할 작업을 결정할 수 있습니다.

그러나 예제에는 디자인 결함이 있습니다. GetDataAsync이라는 메서드에서 데이터가 반환 될 것으로 기대됩니다. 즉, 당신은 단지에 서명을 변경할 수 있습니다, 문제가되지 않습니다 (작업이 수행되지 않는 경우가 차단됩니다)

Task<MyData> GetDataAsync(string parameters); 

이 지금 당신이 결과를 얻을 수의 Result property을 사용할 수있는 Task<T>을 반환하거나 비동기 작업이 완료되면 ContinueWith 메서드를 다시 사용하여 데이터를 처리 할 수 ​​있습니다.

또한, 당신은 당신이 당신의 작업을 취소 여부를 결정하는 매개 변수의 CancellationToken structure 인스턴스를 수행 할 수 있습니다

다시
Task<MyData> GetDataAsync(string parameters, 
    CancellationToken cancellationToken); 

, ContinueWith는 취소에 수행 할 작업을 표시 할 수 있습니다.

이것은 및 async을 사용하는 방법이 Async CTP에서 현재 모델링되는 방식입니다. 그들은 Task 또는 Task<T>를 반환합니다. 코드에서 동일한 작업을 수행하면 이러한 언어 기능을 구울 때 준비가 완료됩니다.

+0

나는 당신이 맞다고 생각하지만, 당신의 모범은 내 머리를 잡기가 훨씬 더 복잡하다. 나는 아직도 그래야만한다는 것을 안다. 인터페이스를 구현하는 클래스에서 어떻게 구현할 것인지, 그리고 예를 들어 WCF 호출을이 클래스로 랩핑하지 않으면 내가 사용할 수 있다고 생각하지 않습니다. 나는 취소하고 계속 작동하는 것에 대해 신경 쓰지 않습니다. 예외가 있거나 데이터가있는 시점을 알 필요가 있습니다. – katit

+0

@katit, http://msdn.microsoft.com/en-us/library/dd537610%28v=VS.100%29.aspx – ebb

+0

Silverlight에서 사용할 수 있습니까? 작업을 사용할 수 없다고 생각합니다. – katit

1

작업을 사용하려면 다음과 같이하십시오. 기억해야 할 유일한 까다로운 점은 TaskScheduler.FromCurrentSynchronizationContext()로 구현 된 UI 스레드에서 콜백을 실행하여 UI가 업데이트되거나 문제가 발생할 경우 messagebox를 표시 할 수 있도록하는 것입니다.

이 물건의 이벤트 중심 특성으로 인해 WCF를 시작하는 버튼을 망치로두면 요청을 보낸 순서대로 결과를 얻지 못할 수도 있습니다. 새 작업을 시작하려는 경우 시작된 작업을 저장하고 마지막으로 시작한 작업을 취소하여이 작업을 방지하거나 작업이 실행되는 동안 후속 요청을 무시할 수 있습니다.

private void button1_Click(object sender, EventArgs e) 
{ 
    GetDataAsync("www.data.com").ContinueWith(result => 
     { 
      if (result.Exception != null) 
      { 
       MessageBox.Show(this, "Error: {0}" + result.Exception, "Error"); 
      } 
      else 
      { 
       foreach (var obj in result.Result) 
       { 
        textBox1.Text += obj.ToString(); 
       } 
      } 
     }, 
     TaskScheduler.FromCurrentSynchronizationContext() 
     ); 

} 

Task<IEnumerable<object>> GetDataAsync(string parameters) 
{ 
    return Task<IEnumerable<object>>.Factory.StartNew(() => 
    { 
     Thread.Sleep(500); 
     // throw new ArgumentException("uups"); 
     // make wcf call here 
     return new object[] { "First", "second" }; 
    }); 
} 
+0

불행히도 Silverlight 4에서 작업을 사용할 수 없습니다. – katit