2

bulkcopy を使用して数百のテーブルをコピーする必要があります。これまでのところ、次のコードを取得しました。

// from UI main thread
private void test1()
{
  LimitedTaskScheduler scheduler = new LimitedTaskScheduler(4);
  TaskFactory factory = new TaskFactory(scheduler);
  foreach (DataRow row in tabList.Rows) // Loop over the rows.
  {
    string tabName = row[tabList.Columns["TableName"]].ToString();
    factory.StartNew<string>( () =>
    {
      Console.WriteLine("{0} on thread {1}", tabName, Thread.CurrentThread.ManagedThreadId);
      TableCopyer tc1 = new TableCopyer();
      // pass progressbar and label into tc1 instance to update the progressbar and label
      tc1.Bar1 = bar1; 
      tc1.L1 = l1;
      tc1.EntityCopy(AppInfo.SrcDBMSPath, AppInfo.DestDBMSPath, tabName, "");
      return tabName;
    });
  }
}

// inside TableCopier class
private void OnSqlRowsCopied(object sender, SqlRowsCopiedEventArgs e)
{
  try
  {
    int rowCopied = int.Parse(e.RowsCopied.ToString());
    double result = (double.Parse(rowCopied.ToString()) / double.Parse(TotalRows.ToString()));
    int prsent = int.Parse(Math.Round((result * 100), 0).ToString());
    SetProgressbar(prsent);
  }
  catch { throw; }
}

LimitedTaskScheduler はhttp://msdn.microsoft.com/en-us/library/ee789351.aspxから来ています

私の質問は

  1. 各スレッド内の前のタスクが終了したときにのみ開始されるように、タスクをチェーンするにはどうすればよいですか? 最大並列スレッドを 4 に制限しました。スレッド内で実行されるタスクは、1 つの終了と別の開始の方法で同じプログレスバーを再利用するため、スレッド内でタスクを連鎖させたいと考えています。

  2. UI、bar1、bar2、bar3、bar4 に 4 つのプログレス バーが描画されています。各プログレスバーを特定のスレッドに関連付けて、ユーザーが同時に 4 つの進行状況を確認できるようにするにはどうすればよいですか?

4

2 に答える 2

0

特定のスレッドについて考えることに自分自身を結びつけることは、あまり意味がないと思います。代わりに、一度に最大 4 つのタスクを同時に実行し、それらのタスクから 4 つの進行状況バーを使用する必要があります。

できることは、これらの進行状況バーをコレクションに入れ、各タスクの開始時にそこから進行状況バーを取得し、タスクの終了時にそこに戻すことです。

ここではスレッド セーフに注意する必要があるため、プログレス バーのコレクションを操作するときはロックを使用するか、 のようなスレッド セーフなコレクションを使用する必要がありますConcurrentQueue。また、プログレス バーの更新は通常、UI スレッドから行う必要があるため、それも処理する必要があります。

于 2012-12-09T15:48:45.683 に答える
-1

各スレッド内の前のタスクが終了したときにのみ開始されるように、タスクをチェーンするにはどうすればよいですか? 最大並列スレッドを 4 に制限しました。スレッド内で実行されるタスクは、1 つの終了と別の開始の方法で同じプログレスバーを再利用するため、スレッド内でタスクを連鎖させたいと考えています。

タスクを連鎖させたい。したがって、UI とは別のスレッドでこれを処理したい場合を除いて、基本的に並列処理は発生しません。では、ループ処理を順番に実行したくないのに、なぜループの反復ごとに新しいタスクを生成したいのでしょうか? タスクで通常の for ループをラップするだけです。

private void test1()
{
    Task.Factory.StartNew(() =>
    {
        foreach (DataRow row in tabList.Rows) // Loop over the rows.
        {
            string tabName = row[tabList.Columns["TableName"]].ToString();

            Console.WriteLine("{0} on thread {1}", tabName, Thread.CurrentThread.ManagedThreadId);
            TableCopyer tc1 = new TableCopyer();
            // pass progressbar and label into tc1 instance to update the progressbar and label
            tc1.Bar1 = bar1;
            tc1.L1 = l1;
            tc1.EntityCopy(AppInfo.SrcDBMSPath, AppInfo.DestDBMSPath, tabName, "");
        }
    });
}

UI、bar1、bar2、bar3、bar4 に 4 つのプログレス バーが描画されています。ユーザーが同時に 4 つの進行状況を確認できるように、各プログレスバーを特定のスレッドに関連付けるにはどうすればよいですか?

これを行うには多くの方法があり、どれが最適かは要件によって異なります。で進行状況バーを参照できますQueue<T>が、テーブルの行と同じ数の進行状況バーが表示されると確信している場合に限ります。

private void test1()
{
    Task.Factory.StartNew(() =>
    {
        var progressBars = new Queue<ProgressBar>(new List<ProgressBar> { bar1, bar2, bar3, bar4 });

        foreach (DataRow row in tabList.Rows) // Loop over the rows.
        {
            // ...

            if(progressBars.Count() == 0}
                throw new Exception("Not enough progress bars setup!");

            tc1.Bar1 = progressBars.Dequeue();

            // ...
        }
    });
}

tabList.Rowsが の場合IEnumerable、次を使用してキューが壊れないようにすることができますTake()

foreach (DataRow row in tabList.Rows.Take(progressBars.Count()))
{ ... }
于 2012-12-06T07:06:58.737 に答える