2013-06-03 1 views
1

비동기 작업을 수행하는 클래스를 만들기 시작했으며 클라이언트가 콜백을 등록하여 일부 결과를 얻길 원합니다. 마지막으로 다음 코드에 도달했습니다. 그냥 예입니다, 나는 TaskFactory하고 여기에작업 팩토리 및 콜백을 사용하여 비동기 메서드 만들기

Action<>, Func<> 클라이언트 기본 예이다 사용하여 일을 더 나은 방법이 있는지 알고 싶습니다 : 여기

Client client2 = new Client(); 
client2.GetClientList(ClientCallBack); 


private static void ClientCallBack(List<Client> listado) 
{ 
    //Receive the list result and do some stuff in UI  
} 

는 클라이언트 클래스 GetCLientList 비동기 예 :

public void GetClientList(Action<List<Client>> Callback) 
{ 
    List<Client> listado=null; 

    Task.Factory.StartNew(() => 
    { 
     listado = new List<Client>{ 
     new Client{ apellidos="Landeras",nombre="Carlos",edad=25}, 
     new Client{ apellidos="Lopez", nombre="Pepe", edad=22}, 
     new Client{ apellidos="Estevez", nombre="Alberto", edad=28} 
     }; 

    //Thread.Sleep to simulate some load 
    System.Threading.Thread.Sleep(4000); 
    }).ContinueWith((prevTask) => 
    { 
     Callback(listado); 
    } 
); 
} 

더 좋은 방법이 있습니까? 내 함수에서 Task을 반환하고 클라이언트 측에 continueWith을 등록 할 수 있다는 것을 알고 있지만, 클래스 내부에 포장하고 싶습니다.

편집

나는 또 다른 예를 게시하도록하겠습니다. 나는 sync/async 버전을 webrequest으로 만들려고했습니다. 은?

public string ExecuteRequest(string url) 
{ 
    HttpWebRequest httpwebrequest = (HttpWebRequest) WebRequest.Create(url); 
    HttpWebResponse httpwebresponse = (HttpWebResponse) httpwebrequest.GetResponse(); 

    using (StreamReader sr = new StreamReader(httpwebresponse.GetResponseStream())) 
    { 
    return sr.ReadToEnd(); 
    } 
} 

public void ExecuteRequestAsync(string uri,Action<string> callbackResult) 
{ 
    Task.Factory.StartNew(() => ExecuteRequest(uri), CancellationToken.None) 
    .ContinueWith((task) => callbackResult(task.Result));   
} 
+1

C# 5.0을 사용할 수 없다고 가정합니다. 맞습니까? – svick

+0

나는 무엇이든 사용할 수 있습니다. 그것은 단지 학습을위한 것입니다. 나는 모든 대답을 받아 들인다. –

답변

5

먼저 올바른이 방법인가, 당신의 방법은 당신이 하나처럼 보이게에서 많이 얻을하지 않을거야, 그래서 실제로 비동기 될 것 같지 않습니다. 만약 당신의 방법의 사용자가 다른 스레드에서 그것을 실행하기로 결정한다면, 그들은 스스로 할 수 있습니다.

둘째, C# 5.0을 사용할 수 있으면 방법을 더 쉽게 사용할 수 있도록 the Task-based asynchronous pattern을 따라야합니다.

public async Task<List<Client>> GetClientListAsync() 
{ 
    var list = new List<Client> 
    { 
     new Client { apellidos="Landeras", nombre="Carlos", edad=25 }, 
     new Client { apellidos="Lopez", nombre="Pepe", edad=22 }, 
     new Client { apellidos="Estevez", nombre="Alberto", edad=28 } 
    }; 

    //Task.Delay() to simulate some load 
    await Task.Delay(4000); 

    return list; 
} 

: 당신은 당신의 코드가 실제로 비동기 만들고 싶었다 경우,

public Task<List<Client>> GetClientListAsync() 
{ 
    return Task.Run(() => 
    { 
     var list = new List<Client> 
     { 
      new Client { apellidos="Landeras", nombre="Carlos", edad=25 }, 
      new Client { apellidos="Lopez", nombre="Pepe", edad=22 }, 
      new Client { apellidos="Estevez", nombre="Alberto", edad=28 } 
     }; 

     //Thread.Sleep to simulate some load 
     System.Threading.Thread.Sleep(4000); 

     return list; 
    }); 
} 

을 또는 : (위의 내 첫 번째 점을 무시하는 이유가 가정하고)두고, 코드는 다음과 같이 수 당신이하지 않은 (또는 수없는)를 사용하는 경우,

var client = new Client(); 
var list = await client.GetClientListAsync(); 
//Receive the list result and do some stuff in UI 

셋째, 두 경우 모두 다음이 같은 async 방법에서 콜백을 사용하지 않고이 방법을 사용할 수 있습니다- await, 코드가 비슷하지만 꽤 옳습니다. 문제는 콜백이 UI 스레드에서 실제로 실행되지 않는다는 것입니다. 이를 위해서는 TaskScheduler.FromCurrentSynchronizationContext()을 사용해야합니다.

또한 ClientGetClientList() 메서드가있는 디자인은 나에게 의심스러워 보입니다. 이러한 방법은 아마도 Client이 아니라 일종의 저장소 개체에 속할 것입니다.

+0

이 함수는 실제가 아니며 테스트를 위해서만 하드 코딩되어있다.그 메소드를 실행하고 콜백에 도달 할 때까지 내 프로그램이 계속 실행되므로 비동기입니다. 왜 현재 비동기식이라고하지 않습니까? 또한, Task.Run()을 사용하여 Task.StartNew를 변경 한 것을 보았습니다. 그러나 다음 링크에서는 동일한 것으로 보이지만 더 적은 매개 변수로 선언했습니다. 당신은 조금 설명 할 수 있겠습니까? http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx –

+0

@CarlosLanderas 예,이 경우 기본적으로 동일합니다. 단지 Task.Run()입니다. 더 짧습니다. – svick

-2

그러나 기다리는 client.GetClientAsync를 사용하면 theard가 차단됩니다.

콜백을 추가하는 새로운 방법은 무엇입니까? 아니면 4.0 TPL을 사용해야합니까?

나는 기다리는 가치가 보이지 않습니다. 현재 스레드를 차단하고 다른 스레드를 잃어 버렸습니다.

+1

질문에 대답하지 않습니다. (묵시적인) 질문에 대답하기 위해,'await'은 현재 스레드를 차단하지 않을 것입니다; 그것은''기다리는''전체 포인트 * '입니다. –