简体   繁体   English

多线程C#

[英]multi threading C#

I am trying to apply brightness/contrast on a image using track bar, since applying on image taking long time. 我正在尝试使用轨迹条在图像上应用亮度/对比度,因为在图像上花费很长时间。 When track bar is scrolled, it's not smooth, it's getting lagged on my form. 滚动跟踪栏时,它不平滑,在我的表单上变得滞后。 Here is my code,is this right method for separating out worker thread from UI (there is no improvement in user experience though)? 这是我的代码,这是从UI分离工作线程的正确方法吗(尽管用户体验没有改善)?

    private void bright_tbr_ValueChanged(object sender, EventArgs e)
    {
        brightness = bright_tbr.Value;
        contrast = contrast_tbr.Value;
        toolTip1.SetToolTip(bright_tbr, brightness.ToString());
        Thread thread = new Thread(new ThreadStart(applyBandC));
        thread.IsBackground = true;
        thread.Start();

    }
     private void applyBandC()
    {
        this.Invoke((MethodInvoker)delegate()
                {
                    lock (this)
                    {
                        create_pixmap(brightness, contrast, 0, 0, 255, 255);
                        Bitmap bmp1 = new Bitmap(bmp);
                        BitmapData data1 = bmp1.LockBits(new Rectangle(0, 0,                                                bmp1.Width, bmp1.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
                        MapLUT(bmp1.Height, bmp1.Width, data1.Scan0);
                        bmp1.UnlockBits(data1);
                        pictureBox2.Image = bmp1;
                    }
                }
    );

    }

Your solution doesn't improve the user experience because your entire "multithreaded" code is wrapped in this.Invoke ! 您的解决方案不能改善用户体验,因为您的整个“多线程”代码都包装在this.Invoke The purpose of Invoke is to execute a delegate on the UI thread . Invoke的目的是在UI线程上执行委托。 Move all your processing code except for the pictureBox2.Image = bmp1; 移动除pictureBox2.Image = bmp1;之外的所有处理代码pictureBox2.Image = bmp1; part out of the delegate passed to this.Invoke and it should work properly. 一部分传递给this.Invoke ,它应该可以正常工作。

As minitech said, when working in a invoke block, you are still blocking the UI. 正如minitech所说,当在invoke块中工作时,您仍在阻塞UI。 You have to prepare the bitmap in the background and assign it in the foreground. 您必须在背景中准备位图,并在前景中分配它。 You also have to make sure that only one prepare task is running simultaniously and you dont want update requests batching up when you are waiting for another updateTask. 您还必须确保只有一个准备任务正在同时运行,并且您不希望在等待另一个updateTask时批处理更新请求。 TPL helps you in this, see the following example code: TPL为此提供了帮助,请参见以下示例代码:

    private Task _runningTask;

    // only call this method from the UI!
    private void UpdateBitmap()
    {
        int brightness = bright_tbr.Value; 
        int contrast = contrast_tbr.Value;
        // only when not yet running
        if (_runningTask == null)
        {
            var ui = TaskScheduler.FromCurrentSynchronizationContext();

            _runningTask = Task.Factory.StartNew<Bitmap>(() =>
            {
                // prepare
                create_pixmap(brightness, contrast, 0, 0, 255, 255);
                Bitmap bmp1 = new Bitmap(bmp);
                BitmapData data1 = bmp1.LockBits(new Rectangle(0, 0, bmp1.Width, bmp1.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
                MapLUT(bmp1.Height, bmp1.Width, data1.Scan0);
                bmp1.UnlockBits(data1);
                return bmp1;
            }).ContinueWith(x =>
            {
                // assign
                pictureBox2.Image = x.Result;

                int newBrightness = bright_tbr.Value;
                int newContrast = contrast_tbr.Value;

                // If the value has changed in the meantime, update again
                if (newBrightness != brightness || newContrast != contrast)
                {
                    UpdateBitmap();
                }
                else
                {
                    _runningTask = null;
                }
            }, CancellationToken.None, TaskContinuationOptions.None, ui);
        }
    }

Is this a web app or windows application(more specifically WPF). 这是Web应用程序还是Windows应用程序(更确切地说是WPF)。 If its a WPF based application, then you can use Dispatcher class, for performing non-UI based tasks, which will be executed on a separate thread and once the processing is over, the result will be pushed back to the main UI thread. 如果它是基于WPF的应用程序,则可以使用Dispatcher类来执行基于非UI的任务,这些任务将在单独的线程上执行,并且一旦处理结束,结果将被推回主UI线程。 For more on Dispatcher : http://weblogs.asp.net/pawanmishra/archive/2010/06/06/understanding-dispatcher-in-wpf.aspx 有关Dispatcher的更多信息, 请访问http : //weblogs.asp.net/pawanmishra/archive/2010/06/06/understanding-dispatcher-in-wpf.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM