Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我应该使用哪种线程形式来提高递归的效率?_C#_Multithreading_User Interface_Recursion - Fatal编程技术网

C# 我应该使用哪种线程形式来提高递归的效率?

C# 我应该使用哪种线程形式来提高递归的效率?,c#,multithreading,user-interface,recursion,C#,Multithreading,User Interface,Recursion,我有两个递归方法,一个接一个,每个方法都为每个节点生成数据,生成任意大小的树。(我无法将两者结合起来,因为第二次迭代取决于第一次迭代的结果——而且,第一次迭代是从叶到根的,第二次迭代是从根到叶的。)我需要为每个节点添加/位置更新生成数据。每次树状态更新时,我都需要将树绘制成缓存位图 我目前正在为此使用BackgroundWorker,但当用户添加大量节点时,事情开始延迟,就好像任务与UI在同一线程上工作一样。(这是我第一次使用BackgroundWorker,但通常不用于处理线程) 我曾经看到M

我有两个递归方法,一个接一个,每个方法都为每个节点生成数据,生成任意大小的树。(我无法将两者结合起来,因为第二次迭代取决于第一次迭代的结果——而且,第一次迭代是从叶到根的,第二次迭代是从根到叶的。)我需要为每个节点添加/位置更新生成数据。每次树状态更新时,我都需要将树绘制成缓存位图

我目前正在为此使用BackgroundWorker,但当用户添加大量节点时,事情开始延迟,就好像任务与UI在同一线程上工作一样。(这是我第一次使用BackgroundWorker,但通常不用于处理线程)

我曾经看到Matt的帖子:
我应该恢复到System.Thread吗?或者它们可能是另一个选项?当进程完成时,我需要在主线程上存储生成的树和一个整数值

[Threading]
private void Commence()
{
    if (worker.IsBusy)
    {
        try
        {
            // I was thinking of fixing this with a timer instead
            worker.CancelAsync();
            while (worker.IsBusy) Thread.Sleep(10);
        }
        catch { return; }
    }
    worker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
    // int radMax; TreeNodeEx rTNH;
    // Call the two recursive methods
    radMax = GenerateDataFromNodes(rTNH, radMax);
    UpdateRenderRegion(); // draw result to cached bitmap
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // draw bitmap to screen
    if (!e.Cancelled) Invalidate();
}

[Algorithm]
private int GenerateDataFromNodes(TreeNodeEx hierarchy, int max)
{
    // set hierarchy values
    max = GenerateScaleAndRadius(hierarchy, max);
    GenerateStartAndSweep(hierarchy);

    return max;
}
private int GenerateScaleAndRadius(TreeNodeEx hierarchy, int max, int radius = 2)
{
    for (int i = 0; i < hierarchy.Nodes.Count; i++)
    {
        max = GenerateScaleAndRadius((TreeNodeEx)hierarchy.Nodes[i], max, radius+1);
    }
    // generation a
    return max;
}
private void GenerateStartAndSweep(TreeNodeEx hierarchy)
{
    for (int i = 0; i < hierarchy.Nodes.Count; i++)
    {
        // generation b-1
    }
}
private void node_SweepAngleChagned(object sender, EventArgs e)
{
    for (int i = 0; i < ((TreeNode)sender).Nodes.Count; i++)
    {
        // generation b-2
    }
}

[Invalidation]
private void UpdateRenderRegion()
{
    if (rTNH != null)
    {
        renderArea = new Bitmap(radMax * rScale * 2, radMax * rScale * 2);
        Graphics gfx = Graphics.FromImage(renderArea);

        gfx.SmoothingMode = SmoothingMode.AntiAlias;
        // pens, graphicspaths, and pathgradients

        // draw parent first

        // draw generations next using the same structure as the parent
        DrawNodes(gfx, p, rTNH, rScale, w, h);

        gfx.Dispose();
    }
}
[线程]
私人文件
{
if(worker.IsBusy)
{
尝试
{
//我想用定时器来解决这个问题
worker.CancelAsync();
while(worker.IsBusy)Thread.Sleep(10);
}
catch{return;}
}
worker.RunWorkerAsync();
}
无效工作线程(对象发送器,工作线程目标)
{
//int radMax;TreeNodeEx rTNH;
//调用这两个递归方法
radMax=从节点生成的数据(rTNH,radMax);
UpdateRenderRegion();//将结果绘制到缓存的位图
}
void worker\u RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
//在屏幕上绘制位图
如果(!e.Cancelled)无效();
}
[算法]
私有int-GenerateDataFromNodes(TreeNodex层次结构,int-max)
{
//设置层次结构值
max=GenerateScaleAndRadius(层次,max);
GenerateStartAndSweep(层次结构);
返回最大值;
}
私有int-GenerateScaleAndRadius(Treenodex层次结构,int-max,int-radius=2)
{
对于(int i=0;i
我想这就是您的代码的问题所在。如果您有一个很大的树,正如您所建议的,并且您的递归是一个很长的过程,那么当您再次调用
comment()
方法时,它将等待并执行
Thread.Sleep(10)
;产生用户界面不响应。像这样重写代码,如果取消了
BackgroundWorker
,它应该调用
RunWorkerCompleted
事件处理程序中的
comment()
方法,而不是等待worker完成。检查代码:

private void Commence()
{
      if (worker.IsBusy)
      {
           worker.CancelAsync();
      }
      else
      {
           worker.RunWorkerAsync();
      }
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
      BackgroundWorker bgw = (BackgroundWorker)sender;
      if (bgw.CancellationPending)
      {
            e.Cancel = true;
            return;
      }
      else
      {
            radMax = GenerateDataFromNodes(rTNH, radMax);
            if (bgw.CancellationPending)
            {
                  e.Cancel = true;
                  return;
            }
            UpdateRenderRegion(); // draw result to cached bitmap
      }
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
      if (!e.Cancelled)
           Invalidate();
      else
           Commence();
}

另外,请注意,在发生Invalidate时(无论出于何种原因),不要同时访问backBuffer(正在使用的位图)。我不知道您是否已经处理了从不同线程访问此位图的权限,但请记住。

“我需要在进程完成后在主线程上存储生成的树和一个整数值。”-这部分没有意义。内存是跨线程共享的。你已经展示了一些方法,它们没有做任何有趣的事情,省略了你讨论过的重要方法的实现……如果它们太大以至于不能发布,就把你的问题浓缩成一个更小的例子,这个例子仍然可以说明问题。哦,任何递归方法都可以作为迭代方法来实现,只要使用
堆栈
,如果这是某种原因造成的问题。@RQDQ好的,我将添加这些方法的压缩版本…您应该发布绘制事件处理程序代码和UpdateRenderRegion();,我不确定GenerateDataFromNodes是否会影响UI,因为它是在后台执行的。。。