2015-01-03 1 views
0

제 WPF 응용 프로그램에 타사 라이브러리를 통합하려고합니다. 이 라이브러리는 개인의 사회 보장 번호로 신용 카드 기록을 수집하는 데 사용됩니다. 기본적으로 void를 반환하는 메서드를 제공합니다. 해당 방법이 완료되면 신용 카드 기록을 수집 할 수 있습니다.유스 케이스의 효율적인 디자인을위한 제안이 필요합니다.

이제이 인원수로이 API를 실행하고 싶지만 한 번에 최대 요청 수의 임계 값을 원합니다. 해당 임계 값에 도달하면 새 요청을 보내기 전에 해당 요청 중 하나가 완료되기를 기다리고 싶습니다. 마지막으로 제출 된 요청 중 하나가 성공 또는 실패 할 때 UI를 업데이트하고 싶습니다. 이 타사 API가 정보를 수집하기 위해 아주 가끔 기다리고 끝낼 수

  1. : 여기

    내 질문입니다. 이 상황에서 Parallel.ForEach 또는 AsParallel과 같은 TPL/PLINQ API를 사용하고 있습니까?

  2. await/async을 사용하여 Run 메서드가 무효를 반환하는 경우 제 3 자 라이브러리 호출에 대한 래퍼를 만들 수 있습니까?

  3. 진행 상황에 대한 UI를 계속 업데이트 할 수 있도록 제출 된 개별 요청을 기다리는 것이 가장 좋은 방법입니다.

설계/구현 방법에 대한 제안 사항 (몇 가지 샘플 코드 포함)을 제공해주십시오. Tasks와 Async/Await에 대한 많은 책을 읽었지 만이 유스 케이스에 가장 적합한 패턴이 무엇인지 혼란스러워 했나요?

+0

당신은 상한과 차단 모음을 사용할 수 있습니다 http://msdn.microsoft.com/en-us/library/dd267301(v=vs.110) .aspx – Paparazzi

+0

감사의 말 귀하의 제안에 대한 밤. 이것은 생산자 - 소비자 패턴을 사용하는 것입니다, 맞습니까? 그렇다면, 나는 그것에 대해서도 읽었지만,이 서드 파티 라이브러리와 어떻게 통합 할 것인지 잘 모르겠다. 어떤 아이디어? –

+0

개념을 이해하기 위해 주로 작은 코드 예제를 읽고/놀았습니다. 예를 들어 필자는 Parallel.ForEach가 I/O를 수행하는 모든 연산에 적합한 후보가 될 수없는 곳을 일부 읽었습니다. 이 제 3 자 API는 데이터 검색을 위해 일부 웹 서비스를 호출하기 때문에 어떤 접근 방식을 실제로 사용해야하는지 생각하고 싶었습니다. –

답변

1

@ lanon이 지적했듯이 API는 동기식입니다 (자연히 비동기적인 I/O 기반 작업을 수행하고 있음에도 불구하고). 따라서 차단으로 간주해야합니다.

귀하의 요구 사항에 대해 알지 못하는 사이에 asyncTask.Run을 권하고 싶습니다. Parallel 또는 Parallel LINQ (AsParallel)를 사용할 수도 있지만 처음에 총 작업 수를 알면 가장 잘 작동합니다.이 시나리오에서이 작업이 적합한 지 여부는 분명하지 않습니다. 또한 기내에있는 동안 다른 작업을 추가해야하는 경우 TPL DataflowRx을 고려할 수도 있습니다. IMO, async 접근 방식은 학습 곡선이 가장 낮습니다. 그러나 Rx는 특히 매우 우아한 디자인을 가지고 있으며 일단 배우면 어디에서나 사용할 수 있습니다.

먼저 자연적인 반환 형식과 예외 처리를 사용하는 유틸리티 메서드가 필요할 것입니다. 나는 당신의 타사 클래스는 이미이 같은하지 않는 이유를 모르겠어요 다음 async 경우

CreditHistory GetCreditHistory(string ssn) 
{ 
    var instance = new Instance(ssn); 
    instance.Run(); 
    if (instance.Success) 
    return instance.CreditHistory; 
    throw ... 
} 

, 당신은 UI 스레드에서 호출해야하는 방법을 쓰기 시작 것, 그리고 백그라운드에서 작업을 실행합니다.

async Task GetCreditHistoryOnBackgroundThreadAsync(string ssn) 
{ 
    try 
    { 
    var history = await Task.Run(() => GetCreditHistory(ssn)); 
    // Update UI with credit history. 
    } 
    catch (Exception ex) 
    { 
    // Update UI with error details. 
    } 
} 

그런 다음 비동기 제한을 추가 할 수 있습니다. 이 사용하는 하나의 방법입니다 내장 SemaphoreSlim :

private readonly SemaphoreSlim _mutex = new SemaphoreSlim(10); 
async Task GetCreditHistoryOnBackgroundThreadAsync(string ssn) 
{ 
    await _mutex.WaitAsync(); 
    try 
    { 
    var history = await Task.Run(() => GetCreditHistory(ssn)); 
    // Update UI with credit history. 
    } 
    catch (Exception ex) 
    { 
    // Update UI with error details. 
    } 
    finally 
    { 
    _mutex.Release(); 
    } 
} 
+0

답변 해 주셔서 감사합니다. 이 애플리케이션이 신용 카드 기록 검색을 위해 전송할 요청 수를 알 수 있습니다. 위에서 제공 한 코드 샘플은 어떻게 변경됩니까? 그래도이 아이디어가 마음에 든다. 코드가 크게 변경된 경우 기존의 코드를 제거하지 않고 답변에 추가하도록 요청할 것이다. –

+0

@PaulSnow :'await Task.WhenAll'을 사용하면 여러 동시 작업을 수행 할 수 있습니다. –

+0

ok, thanks again –

2

어떤 방법이 가장 좋을지 말할 수 없습니다.

Degree of Parallelism에 대한 MSDN의 샘플을 사용할 수 있습니다. 그러나이 경우 System.Threading.Tasks.Dataflow 네임 스페이스를 설치해야합니다.

var myOptions = new ParallelOptions { MaxDegreeOfParallelism = 4 }; 

Parallel.For(0, NumberOfClients, myOptions, i=> 
{ 
    // Code to run 
}); 

그럼, 첫 번째 질문에 대한 대답은 YES, 귀하의 목록에 아주 좋은 후보입니다 :

Parallel 클래스도 당신이 병렬 처리 수준을 지정할 수있는 옵션을 가지고 있습니다 당신의 업무를 수행하십시오.

두 번째 대답은 입니다.

마지막

이 같은 UI 스레드에서

전화 할 수있는 일 :

Task.Factory.StartNew(DoWork); 

당신은 취소를 지원하기 위해 CancellationToken를 사용할 수 있습니다. 또한 필요한 동작을 얻으려면 메서드의 다른 오버로드를 사용할 수 있습니다. 또한 얼마나 많은 레코드가 진행되었는지를 나타내는 Value 속성을 가질 수 있습니다.이 속성은 당신이 ProgressBar와 바인딩, 제대로

public void DoWork() 
{ 
    var myOptions = new ParallelOptions { MaxDegreeOfParallelism = 4 }; 

    Parallel.For(0, NumberOfClients, myOptions, i=> 
    { 
     ThirdPartyLibrary Instance = new Instance(SSN[i]); 
     Instance.Run(); 
     Interlocked.Increment(ref value); 
     RaisePropertyChanged("Value"); 
    }); 
} 

몇 가지 단어에 대한 Interlocked.Increment(ref value)를 업데이트 할 수 있습니다 : 그것은 the data race condition을 방지하기 위해 원자 작업으로, 지정된 변수의 증분을 수행하고 결과를 저장합니다.

+0

감사합니다 stukselbax. 그 void를 불평 Instance.Run와 함께 기다리고 사용하려고하면 컴파일 오류가 발생합니다. 당신이 사용할 수 있다고 했잖아요. 내가 뭘 놓치고 있니? –

+1

아마도 'async'(http://msdn.microsoft.com/en-us/library/hh191443.aspx)로 표시되고 메소드를 차단하는 메소드 인 Instance.Run()을 래핑해야합니다. 그것 await 키워드와 함께. – stukselbax

관련 문제