2016-12-12 10 views
0

ユーザーがログインした後にいくつかのコントロールを作成しようとしています。バックグラウンドスレッドでコントロールを追加しますか?

私は3つのタブを持つTabControlを持っています。ログインする最初のもの、2番目のものはたくさんのタイルを表示する必要がある場所です(MahApps.Metroタイル)。各タイルはホテルの部屋を表しています。

3番目のタブには、未確定の進行状況バーが表示されます。ユーザーがログインすると、このタブが表示されます。私はこれをどうやっ

//User is logged in, so display the progress bar and add controls 
    tabControl.SelectedIndex = 2; // display the progress bar tab 

    private void populateHotel(Hotel hotel) 
    { 
     List<Room> rooms = hotel.rooms; 
     Tile tile; 
     tile_wrapper.Children.Clear(); 
     foreach (Room room in rooms) 
     { 
      sql.insertHotelRoom(room); 
      tile = new Tile(); 
      tile.Title = room.room_num; 
      tile.Content = room.name_fa;    
      tile.FontFamily = titleRooms.FontFamily; // titleRooms is a textbox 
      tile.TitleFontSize = item1.TitleFontSize; // item1 is an already created tile 
      tile.FontSize = item1.FontSize; 
      tile_wrapper.Children.Add(tile); 

     } 
     // Now display the rooms tab 
     tabControl.SelectedIndex = 1; 
    } 

問題は、これはそれがすべてのタイルを作成するまでプログレスバーを含めて、UIスレッドとすべてのフリーズがフリーズ、です。

プログレスバーがまだ応答するようにコントロールを追加するにはどうすればよいですか?何をやっている

答えて

1

はそれを表示するUIコードでHotelを挿入ビジネスコードを混合することです。ビジネスコードとUIコードを混在させることは良い考えではありません。 UIがあなたのinsertHotelRoom操作を待つ必要があり、ユーザーの入力に反応できないため、これが作成する保守性の問題に加えて、あなたの問題に寄与しています。

あなたが最初にすべきことは、あなたの懸念を分離することである。

private List<Room> insertHotelRooms(Hotel hotel) 
{ 
    List<Room> rooms = hotel.rooms; 
    foreach (Room room in rooms) 
    { 
     sql.insertHotelRoom(room); 
     rooms.Add(room); 
    } 
    return rooms; 
} 


private void populateHotelTab(List<Room> rooms) 
{ 
    Tile tile; 
    tile_wrapper.Children.Clear(); 
    foreach (Room room in rooms) 
    { 
     tile = new Tile(); 
     tile.Title = room.room_num; 
     tile.Content = room.name_fa;    
     tile.FontFamily = titleRooms.FontFamily; // titleRooms is a textbox 
     tile.TitleFontSize = item1.TitleFontSize; // item1 is an already created tile 
     tile.FontSize = item1.FontSize; 
     tile_wrapper.Children.Add(tile); 

    } 
    // Now display the rooms tab 
    tabControl.SelectedIndex = 1; 
} 

あなたは今タスクで操作を実行し、バックUIスレッドへのUI操作を派遣することができます

Task insertRoomsTask = Task.Run(() => { 
    List<Room> rooms = insertRooms(hotel); 
    tile_wrapper.Dispatcher.Invoke(() => populateHotelTab(rooms)); 
}); 
+0

populateHotelTabのforeachループにThread.Sleep(1000)を追加すると、テストとして、 UIはまだ応答する必要がありますか?私はこれをしましたが、プログレスバーはまだフリーズしています。 – SMahdiS

+0

@SMahdiS:どのforeachループですか? 'pop.HotelTab'に' Thread.Sleep'を追加すると、UIはまだフリーズします。これは、UIスレッドをフリーズする場合に予想される動作です。しかし、なぜあなたはそれをしますか?ソリューションのポイントは、UIスレッドの外で時間のかかる作業を行うことです。タスクで 'Thread.Sleep'を使うのはお勧めできません。実行しているスケジューラーが分からないからです。 – Sefe

+0

私はたくさんのことを学んだ、ありがとう。ところで、そのことが何であるか: "()=> {}"。それは代表者ですか?もしそうでなければ、それは何で、私は何のためにgoogleするべきですか?私はJavaプログラミングに慣れていて、これらのことは私にとっては新しく思えます。 – SMahdiS

0
//User is logged in, so display the progress bar and add controls 
tabControl.SelectedIndex = 2; // display the progress bar tab 

private void populateHotel(Hotel hotel) 
{ 
    List<Room> rooms = hotel.rooms; 
    Tile tile; 
    tile_wrapper.Children.Clear(); 

    // Use a count variable to keep track of how many rooms have been processed 
    int count = 0; 

    foreach (Room room in rooms) 
    { 
     // Update the value of the progress bar 
     progressbar1.Value = count++ * 100/rooms.Count; 
     // Cause the progress bar to refresh 
     progressbar1.Refresh(); 

     sql.insertHotelRoom(room); 
     tile = new Tile(); 
     tile.Title = room.room_num; 
     tile.Content = room.name_fa;    
     tile.FontFamily = titleRooms.FontFamily; // titleRooms is a textbox 
     tile.TitleFontSize = item1.TitleFontSize; // item1 is an already created tile 
     tile.FontSize = item1.FontSize; 
     tile_wrapper.Children.Add(tile); 

    } 
    // Now display the rooms tab 
    tabControl.SelectedIndex = 1; 
} 
+0

いいえプログレスバーは不確定なMetroProgressBarであり、Refresh()メソッドはありません。それはUpdateLayout()を持っていますが、それも動作しませんでした。 – SMahdiS

+0

populateHotel()という関数にUIロジックを持たせるのは理想的ではありません。 バックグラウンドワーカーを使用してSQL挿入(https://msdn.microsoft.com/fr-fr/library/cc221403(v=vs.95).aspx)を行うことができますが、まずアプリケーションを変換しようとします非同期呼び出しを使用する。スレッドを手作業で操作する必要はなく、非同期コールバックを使用して、メインのUIスレッドがすべての応答を維持するのに十分な時間を確保することができます。 –

+0

いいえ、そうではありません。 3つ目のタブに割り当てることができる各部屋が更新されたときに呼び出されるデリゲートを作成することをお勧めします。その後、UIから別のスレッドでpopulateHotel()を実行できます。 –

関連する問題