2017-01-13 3 views
0

私のDALでsqlクエリを実行するBackgroundWorkerがビューにあります。foreachループ中にDALから値を返すBackgroundWorker

私の見解では、ユーザーが作業が完了していることを知るように回転を続けるプログレスバーもあります。

SQLクエリは、私がどこのいずれかの条件に移入することを、条件List<string>の一つとして受け取り、そのコードはこのようなものです:あなたは上記気づくよう

using (SqlConnection conn = new SqlConnection(_myHost)) 
     { 
      conn.Open(); 

      foreach (string item in myList) 
      { 
       query = "select * from (" + 
        "//big query with inner joins here" + 
        ") a " 

       using (SqlCommand cmd = new SqlCommand(query, conn)) 
       { 
        SqlDataReader reader = cmd.ExecuteReader(); 
        dt.Load(reader); 
       } 
      } 

、私が通ります私のリスト内のすべてのアイテムは、where句(上記は省略)で個別にクエリを実行し、出力がある場合、foreachが完了したデータテーブルに出力を追加して、ビューレイヤに返し、グリッドビューのデータソースになります。

私は、クエリのどの%が完了したかをサーバーに問い合わせることはできませんが、foreachループの完了%をユーザーに提供できる可能性があります。

私は何を把握しようとしていますがへの道である:int iカウンターを追加、私はシンプルで検出された可能性が私の見解に

戻り、ループの現在の反復、および各foreachの上でそれをインクリメントする、または何が質問されているかを知らせるために、おそらく最初にstring itemがあります。

コードが実行されると、その値を自分のビューに戻す方法がわかりません。私はC#4タプルを考慮しましたが、メソッドが完了した後に返されるのはforeachの実行中ではなく、返されるため動作しません。

アイデア?

+0

あなたがイベントを発生させるか、呼び出すことができます。この

// this code is the DoWork event of the BackgroundWorker private void bgw_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker bkw = sender as BackgroundWorker; ..... using (SqlConnection conn = new SqlConnection(_myHost)) { conn.Open(); int counter = 1; int total = myList.Count; foreach (string item in myList) { ..... WorkerItem item = new WorkerItem() { Counter = counter, Item = item}; int progress = (100 * counter/total); bkw.ReportProgress(progress, item); counter++; } } } public class WorkerItem { public int Counter {get;set;} public string Item {get;set;} ... add other properties if you like ..... } 

のようなものを書くことができますループ内から委譲します。 – RQDQ

+0

_view_とはどういう意味ですか?これはWinFormsのアプリですか、WPFのものなのでしょうか?また、このコードはBackgroundWorkerのDoWorkメソッドの一部ですか? – Steve

+0

そのWinforms App ... shoud'veも同様にそれをタグ付けしました。ごめんなさい。 –

答えて

2

BackgroundWorkerの内側に戻ってあなたのアプリケーションに事務の状態を通信するための最も簡単な方法はReportProgress methodを呼び出すProgressChangedイベントを上げ、どこであなたのコード内の適切なそれをキャッチされたアプリ。

このイベントはフォームがあるスレッド(UIスレッド)で発生しますので、trying to access UI components from a non UI threadに問題はありません。

だから、例えば、あなたはその後のBackgroundWorkerを起動して、このようにReportProgressイベントを処理することができ、あなたのWinフォームのコードが

BackgroundWorker bkw = new BackgroundWorker(); 
bkw.WorkerReportsProgress = true; 
bkw.WorkerSupportsCancellation = true; 
bkw.ProgressChanged += bgw_ProgressChanged; 
bkw.DoWork += bgw_DoWork; 
bkw.RunWorkerAsync(); 
... 

private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    WorkerItem item = e.UserState as WorkerItem; 
    ... update a progress bar, show the current item in a label etc... 
    Console.WriteLine($"Completed: {e.ProgressPercentage}% {WorkerItem.Counter} {WorkerItem.Item}"); 
} 
+1

ReportProgressの最初の引数は、完了率を表すように設計されています(intとして)。典型的には、その引数に使用される '(100 * counter/total)'のような値が計算されています。 – Uueerdo

+0

はい、それは本当です、私はあなたが任意のオブジェクトを呼び出し元に戻すことができるという事実を示すことにもっと関心がありました。これにより、単純な進捗率よりも多くの可能性がコーラーコードに与えられます。 – Steve

+1

ええ、それが必要なときは、通常は0の割合を渡し、渡されたステータスオブジェクトの情報を含めます。 ProgressChangedEventArgsのプロパティがProgressPercentage(コードの2番目のセクションが示すように)という名前が付けられて以来、言及する価値があると思いました。 – Uueerdo

-1

これは片方向です。デリゲートをバックグラウンドスレッドで実行されているメソッドに渡します。

public void Run(Action<int> update) 
{ 
    using (SqlConnection conn = new SqlConnection(_myHost)) 
    { 
     conn.Open(); 

     int index = 0; 

     foreach (string item in myList) 
     { 
      //Perform query 

      //Notify the caller of progress 
      update(index); 

      index++ 
     } 
    } 
} 

バックグラウンドスレッドでコールバックが実行されることに注意してください。私は、BackgroundWorkerのに組み込まれてReportProgressメソッドを忘れ

EDIT

。リサイズで

https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.reportprogress(v=vs.110).aspx