2015-05-08 25 views
1

我試圖從MongoDB集合中檢索數據,但是發生了一些奇怪的事情。如果我顯示一個MessageBox的數據獲取工作,如果我不這樣做。MongoDB無窮查找ToListAsync

static class MongoDBController { 
    static MongoClient client = new MongoClient("mongodb://localhost"); 

    public static async Task<List<Course>> GetCourses(string dbName = "school") {    
     // Get our course collection 
     var db = client.GetDatabase(dbName); 
     var collection = db.GetCollection<Course>("courses"); 

     // Create an empty filter 
     var filter = new BsonDocument(); 

     // Use the empty filter to get all courses from the database 
     return await collection.Find(filter).ToListAsync(); 
    } 
} 

上面的代碼獲取內容從數據庫中,下面的代碼 - 在我Form1.cs發現 - 地方一個ListBox中。

private void FillCourseList() { 
    Task<List<Course>> courseTask = MongoDBController.GetCourses(); 

    MessageBox.Show("Fetching worked (yay!)"); 

    // get the result 
    List<Course> result = courseTask.Result; 

    // Show every course found in the resultset 
    foreach (Course s in result) { 
     listBox_overview_vakken.Items.Add(s); 
    } 
} 

現在,如果我刪除擷取工作(耶!)彈出列表框我永遠不會被填補。

我在做什麼錯?

+1

我不確定什麼會導致此類行爲(SynchronizationContext有些棘手的問題?),但我建議您閱讀http://blog.stephencleary.com/2012/07/dont-block-on-異步code.html。 –

+1

這個'courseTask.Result'是一個阻塞調用,爲了利用'async',你可能希望將你的'FillCourseList'改爲'private async Task FillCourseList'並且執行'... result = await courseTask.ConfigureAwait(假);''''''''''''''''''''''''''''你也應該爲你的調用堆棧中的方法一直「起泡」異步/等待簽名。 – Alex

+0

@Alex,感謝您對此的意見,讓我解決了我的問題。 –

回答

1

正如Alex所指出的那樣,問題的解決方案是使FillCourseList同步。這允許程序在從數據庫中獲取數據時繼續運行。顯然,我之前遇到的阻止電話是問題的原因。這確實增加了對Windows窗體的需求thread-safe calls

private delegate void SetListCallback(List<Course> result); 

    private async Task GetCourseList() { 
     Task<List<Course>> courseTask = MongoDBController.GetCourses(); 
     List<Course> result = await courseTask.ConfigureAwait(false); 

     // When finished, fill the listbox 
     FillCourseList(result); 
    } 

    private void FillCourseList(List<Course> result) { 
     // If the calling thread's ID doesn't match the creating thread's ID 
     // Invoke this method on the correct thread via the delegate 
     if (this.listBox_overview_vakken.InvokeRequired) { 
      SetListCallback d = new SetListCallback(FillCourseList); 
      this.Invoke(d, result); 
     } else { 
      foreach (Course s in result) { 
       listBox_overview_vakken.Items.Add(s); 
      } 
     } 
    } 
+0

一個很好的答案,包括封送回UI線程 – Alex

+1

'async void'只適用於頂級事件處理程序。改用'async Task' –