2

我需要使用批量复制复制数百个表。到目前为止,我得到了以下代码。

// 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。我想在线程中链接任务,因为在线程中执行的任务将以一种完成和另一个开始的方式重用相同的进度条。

  2. 我在 UI 上绘制了 4 个进度条,bar1、bar2、bar3、bar4。如何将每个进度条与特定线程相关联,以便用户可以同时看到 4 个运行进度?

4

2 回答 2

0

I think it doesn't make much sense to tie yourself into thinking about specific threads. Instead, what you want is that your tasks run concurrently at most 4 at a time and you want to use your 4 progress bars from those tasks.

What you could do is to put those progress bars into a collection, and then take a progress bar from there at the start of each task and return it back there at the end of the task.

You have to be careful about thread-safety here, so you should either use locks when working with the collection of progress bars, or use a thread-safe collection like ConcurrentQueue. Also, updating the progress bar usually has to be done from the UI thread, so you will have to take care of that too.

于 2012-12-09T15:48:45.683 回答
-1

我如何链接任务,以便每个任务仅在每个线程中的先前任务完成时才开始?我将最大并行线程限制为 4。我想将线程内的任务链接起来,因为在线程中执行的任务将以一种完成而另一个开始的方式重用相同的进度条。

您想将您的任务链接在一起。所以基本上没有发生并行处理,除了您希望在与 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 上绘制了 4 个进度条,bar1、bar2、bar3、bar4。如何将每个进度条与特定线程相关联,以便用户可以同时看到 4 个运行进度?

有很多方法可以做到这一点,这实际上取决于您对哪种方法最好的要求。您可以引用 a 中的进度条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.RowsIEnumerable,那么您可以使用 确保队列不会中断Take()

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