2

내가 비동기 프로그래밍과 WP8 새로운 오전, 이것은 내 첫 번째 응용 프로그램입니다 내가보기 뒤에 내 코드에서 Dispatcher.BeginInvoke (..)윈도우 폰 8 Dispatcher.BeginInvoke 작동하지 않는 비동기

몇 가지 문제를 가지고 클래스, 두 번째 탭에 대한 피벗 비동기 비동기로 데이터를로드하려고합니다.

public partial class ReminderPivot : PhoneApplicationPage 
    { 
     #region Reminder Members 
     private ReminderViewModel _model; 
     private IRepository _repository; 
     #endregion Reminder Members 

     #region Constructors 
     public ReminderPivot() 
     { 
      InitializeComponent(); 
      _model = new ReminderViewModel(); 
      _repository = new LocalStorageRepository(); 

      LoadData(); 
      LoadAsyncData(); 

      this.DataContext = _model; 

     } 
     #endregion Constructors 

     public void LoadData() 
     { 
      IEnumerable<Reminder> activeList = _repository.GetRemindersByStatusId(2); 
      if (activeList != null) 
      { 
       foreach (var reminder in activeList) 
       { 
        _model.ActiveReminders.Add(reminder); 
       } 
      } 
     } 
     public void LoadAsyncData() 
     {    
      Action action =() => 
      { 
       Thread.Sleep(5000); 

       IEnumerable<Reminder> inactiveList = _repository.GetRemindersByStatusId(3); 
       if (inactiveList != null) 
       { 
        _model.InctiveReminders = new System.Collections.ObjectModel.ObservableCollection<Reminder>(inactiveList); 
       } 
      }; 

      Dispatcher.BeginInvoke(action); 
     } 

것은 인이 정지 블록 내 UI 스레드 그 다음은

내가 지금 가지고있는 것입니다. 내가 여기서 무엇을 놓치고 있니?

EDIT : XAML에서 ModelBinded 인 ViewModel ObservableCollection에 비동기 데이터를로드하는 것이 아이디어입니다.

Task.Factory (...) 등이있는 다른 스레드에서 비동기 호출을 시도하면 UI 스레드가 아닌 다른 스레드에서 바인딩을 변경하면서 충돌이 발생합니다.

+0

내가 Dispatcher.BeginInvoke'는 UI 스레드에서 코드를 실행합니다'... 비동기 사용을 제안 코드에 아무것도 표시되지 않습니다, 단지로 파견 점점 나중에 실행! –

+0

안녕하세요 @PedroLamas. 그러면 질문은 어떻게로드 할 수 있습니까 비동기? Task.Factory (..)로 시도하고 별도의 스레드에서 만들면 업데이트하는 목록이 ListBox에 바인딩되어 있기 때문에 충돌이 발생합니다 .. –

+1

'Task.Factory'를 사용하는 것이 확실히 최선의 가능성은 여기에 ... –

답변

2

@ PedroLamas의 제안을받은 후, 이것이 가장 좋은 방법인지 가장 우아하지만 작업이 완료되는지 확실하지 않습니다.

Im는 Task.Factory를 사용하여 다른 스레드에서 완료하는 데 걸리는 시간이 걸리므로 기다리는 중이며 결국에는 Dispatcher로 UI를 업데이트합니다.

public async void LoadAsyncDataWithTask() 
     { 
      IEnumerable<Reminder> inactiveList = null; 
      Action action =() => 
      { 
       Thread.Sleep(2000); 
       inactiveList = _repository.GetRemindersByStatusId(2); 
      }; 

      await Task.Factory.StartNew(action); 

      Action action2 =() => 
      { 
       if (inactiveList != null) 
       { 
        foreach(var item in inactiveList) 
        { 
         _model.InctiveReminders.Add(item); 
        } 
       } 
      }; 

      Dispatcher.BeginInvoke(action2); 

     } 
+1

그게 작동합니다 (+1). 'GetRemindersByStatusId'를 비동기로 만들어서이 레벨에서 일을 좀 더 편하게 유지할 수 있습니다. 코드의 나머지 부분에 따라 다릅니다. 내가 람다의 앞에이 배치 비동기 같은 일을 할 수있었습니다 8 윈도우 폰으로 –

+1

:; TClock.RestTimerCanvas Dispatcher.BeginInvoke (비동기() =이> { 는 Task.Delay (125)을 기다리고 있습니다 .Children.Clear(); }); – Stonetip

1

당신이 작품을 발견하고 Task을 사용 한 것은, Thread.Sleep를 사용하여 당신은 여전히 ​​이유없이 ThreadPool이의 스레드를 차단하고 아주 최신된다.

(배경) ThreadPool 스레드 중 하나에서 실행되는 일회용 System.Threading.Timer (see MSDN reference)을 사용하면이 문제를 방지 할 수 있습니다. 그런 다음 타이머 콜백 끝에 Dispatcher.BeginInvoke(...)을 사용하여 UI를 업데이트하십시오. 예를 들어

는 :

 var timer = new System.Threading.Timer(
      state => 
       { 
        // ... your code to run in background 

        // ... call BeginInvoke() when done 
        Dispatcher.BeginInvoke(() => MessageBox.Show("done")); 
       }, 
      null, 
      5000, 
      System.Threading.Timeout.Infinite); 
+0

Hey Paul, 정보 주셔서 감사합니다 +1. Thread.Sleep은 메소드가 작동 중임을 테스트하는 것 (더 큰로드 시간, 많은 데이터 처리, 노력한 작업 등을 시뮬레이트하기 위해)이었습니다. 생산 코드에서 이런 종류의 것은 존재하지 않습니다 :-p. –