当后台工作进行中时,不能移动主窗体

时间:2017-04-09 11:33:58

标签: c# multithreading winforms focus

我正在Windows Forms中编写一个简单的图片混合器。虽然它工作得很好我有一个问题 - 在应用程序正在进行中 - 我无法移动主Winodow表单。该应用程序允许两个线程在后台工作。当只有一个人忙的时候,如果我试图拖动窗口,它会有一个延迟响应(好像需要时间来获得焦点)。当两个背景建造者完成他们的任务时,我根本无法移动主要形式。完成后我可以再次移动窗口。 我认为通过这个'作为另一个线程的参数可能是问题,但我复制了我需要的字段,以防我已经添加了这个.Activate()'在调用单独的线程之后。无论如何,这没有任何区别。

这就是我打电话给工人的方式:

private void PerformBlending()
    {
        if (!bw2.IsBusy)
        {
            bw2.RunWorkerAsync(this);
            this.Activate();
        }
        else
        {
            bw3.RunWorkerAsync(this);
            this.Activate();
        }
    }

private void bw2_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker bw = sender as BackgroundWorker;
        Form1 mainForm = e.Argument as Form1;
        Bitmap leftBmp = new Bitmap(mainForm.buttonPic1.BackgroundImage);
        Bitmap rightBmp = new Bitmap(mainForm.buttonPic2.BackgroundImage);
        Bitmap resultBmp;
        int leftX = leftBmp.Width; int leftY = leftBmp.Height;
        int rightX = rightBmp.Width; int rightY = rightBmp.Height;
        int x = leftX < rightX ? leftX : rightX;
        int y = leftY < rightY ? leftY : rightY;
        resultBmp = new Bitmap(x, y);
        double alfa = mainForm.trackBarValue;
        for (int i = 0; i < x; ++i)
        //Parallel.For(0, x, i =>
        {
            for (int j = 0; j < y; ++j)
            {
                bw.ReportProgress((int)(((double)i / (double)y + (double)1 / (double)x) * 100));

                int leftR = (i < leftX && j < leftY) ? (int)(alfa * leftBmp.GetPixel(i, j).R) : 0;
                int leftG = (i < leftX && j < leftY) ? (int)(alfa * leftBmp.GetPixel(i, j).G) : 0;
                int leftB = (i < leftX && j < leftY) ? (int)(alfa * leftBmp.GetPixel(i, j).B) : 0;

                int rightR = (i < rightX && j < rightY) ? (int)((1 - alfa) * rightBmp.GetPixel(i, j).R) : 0;
                int rightG = (i < rightX && j < rightY) ? (int)((1 - alfa) * rightBmp.GetPixel(i, j).G) : 0;
                int rightB = (i < rightX && j < rightY) ? (int)((1 - alfa) * rightBmp.GetPixel(i, j).B) : 0;

                int r = leftR + rightR;
                int g = leftG + rightG;
                int b = leftB + rightB;
                resultBmp.SetPixel(i, j, Color.FromArgb(r, g, b));
            }
        }//);
        e.Result = resultBmp;

    }

1 个答案:

答案 0 :(得分:1)

要扩展@ LarsTech的评论,您当前的进度计算甚至不依赖于j,因此请将ReportProgress调用移到内部循环之外。这可以通过减少通话次数来帮助提高响应速度,甚至不会改变ProgressBar的行为。

for (int i = 0; i < x; ++i)
    //Parallel.For(0, x, i =>
    {
        bw.ReportProgress((int)(((double)i / (double)y + (double)1 / (double)x) * 100));

        for (int j = 0; j < y; ++j)
        {
            int leftR = (i < leftX && j < leftY) ? (int)(alfa * leftBmp.GetPixel(i, j).R) : 0;
            int leftG = (i < leftX && j < leftY) ? (int)(alfa * leftBmp.GetPixel(i, j).G) : 0;
            int leftB = (i < leftX && j < leftY) ? (int)(alfa * leftBmp.GetPixel(i, j).B) : 0;

            int rightR = (i < rightX && j < rightY) ? (int)((1 - alfa) * rightBmp.GetPixel(i, j).R) : 0;
            int rightG = (i < rightX && j < rightY) ? (int)((1 - alfa) * rightBmp.GetPixel(i, j).G) : 0;
            int rightB = (i < rightX && j < rightY) ? (int)((1 - alfa) * rightBmp.GetPixel(i, j).B) : 0;

            int r = leftR + rightR;
            int g = leftG + rightG;
            int b = leftB + rightB;
            resultBmp.SetPixel(i, j, Color.FromArgb(r, g, b));
        }
    }//);

此外,使用LockBits将有助于实际表现。由于这部分是一个自己的主题,而且我不太熟悉,我会给出一些可能有助于你开始的链接:

LockBits vs Get/Set Pixel

How do I conver my get GetPixel/SetPixel color processing to Lockbits

对于另一种方法:

Faster Alternatives to SetPixel and GetPixel for Bitmaps for Windows Forms App