2011-05-13 5 views
4
private void cmbPlatform_SelectedIndexChanged(object sender, EventArgs e) 
{ 
    string platform = cmbPlatform.Text; 
    UpcomingGameFinder gameFinder = new UpcomingGameFinder(); 
    Task.Factory.StartNew<IEnumerable<Game>>(() => gameFinder.FindUpcomingGamesByPlatform(platform)) 
     .ContinueWith((i) => PlaceGameItemsInPanel(i.Result));   
} 

private void PlaceGameItemsInPanel(IEnumerable<Game> games) 
{ 
    int yPosition = 0; 
    foreach (var game in games) 
    { 
     GameItem item = new GameItem(game); 
     item.Location = new Point(0, yPosition); 
     panelGameItemsHolder.Controls.Add(item); 
     yPosition += 125; 
    } 
} 

당연히 나는 여기에서 뭔가 잘못하고 있습니다. 내 생각은 Tasks에서 꽤 새로운 것입니다. 따라서이 문맥에서 어떻게 작동할지는 모르겠습니다.이 컨텍스트에서 작업을 어떻게 사용할 수 있습니까?

기본적으로 FindUpcomingGames()는 완료하는 데 오랜 시간이 걸리므로 해당 메서드에서 반환 된 컬렉션을 가져 와서 N 개의 GameItem 개체 (사용자 정의 컨트롤)를 만들고 여기에있는 패널에 배치합니다. Windows Forms.

내가이 오류 메시지가 얻을 :

크로스 스레드 작업을 유효하지 : 제어 'panelGameItemsHolder'가에 만들어진 스레드가 아닌 다른 스레드에서 액세스 .

의견이 있으십니까?

+1

에서 확인할 수 있습니다. 현재이 문제는 현재 무엇입니까? 그것은 컴파일되지 않거나 올바른 결과를주지 못합니까? – Tejs

+0

@Tejs : 더 많은 정보로 편집하겠습니다. :) –

답변

5

PlaceGameItemsInPanel 메서드는 UI 항목과 상호 작용하기 위해 UI를 전환해야합니다. 가장 쉬운 방법은 UI 스레드에서 ContinueWith를 수행하는 것입니다. 즉

private void cmbPlatform_SelectedIndexChanged(object sender, EventArgs e) 
{ 
    var uiContext = TaskScheduler.FromCurrentSynchronizationContext(); 
    string platform = cmbPlatform.Text; 
    UpcomingGameFinder gameFinder = new UpcomingGameFinder(); 
    Task.Factory.StartNew<IEnumerable<Game>>(() => gameFinder.FindUpcomingGamesByPlatform(platform)) 
     .ContinueWith((i) => PlaceGameItemsInPanel(i.Result), uiContext);   
}  

이 cmbPlatform_SelectedIndexChanged (여기에 보이는대로, 콤보 상자에서 이벤트를 처리 않다면이 될 것입니다) UI 스레드에서 일어나고 있다고 가정합니다. 따라서 현재 SynchronizationContext에 대한 참조를 가져온 다음 ContinueWith에있는 SynchronizationContext를 사용하여 올바른 SynchronizationContext에서 실행되는지 확인할 수 있습니다.

자세한 내용은 http://blogs.msdn.com/b/pfxteam/archive/2009/09/22/9898090.aspx

+0

하지만 어떻게해야합니까? 내가 일반적으로 작업과 스레딩에 익숙하지 않다는 것을 기억하십시오. :) –

+0

+1이 답변을 주셔서 감사합니다; 정확히 내가 찾던 것이 었습니다. –

0

.ContinueWith 대리인에서 작업 할 것입니다. 개체를 만든 후에는 일부 컬렉션 (이상적으로는 관찰 가능한 컬렉션)에 추가하면 UI가 자동으로 업데이트됩니다. 물론 바인딩 된 관찰 가능한 컬렉션을 사용하지 않으면 UI 컨트롤을 직접 업데이트해야합니다. (크로스 스레드 통신에주의하십시오.)

0

잘 사용하고 있지만 잘된 것 같습니다. 워크 플로우를 재고해야합니다. FindUpcomingGames()가 오랜 시간이 걸리는 경우 가능한 한 빨리 백그라운드에서 시작하고 결과를 캐싱하거나 리팩토링하는 것이 좋습니다. 지금 작업을 사용할 때 실제로 비동기로 작업하지 않습니다. 당신은 방금 작업을 시작한 다음 작업이 끝나기를 기다리고 있습니다.

관련 문제