2013-04-28 2 views
2

Часть кода:C# BackgroundWorker и TrackBar

Функция, которая блокирует BitmapData:

public static BitmapData LockData(Bitmap bitmap) 
    { 
     Rectangle bitmapRect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); 
     BitmapData bitmapData = bitmap.LockBits(bitmapRect, ImageLockMode.ReadWrite, bitmap.PixelFormat); 

     return bitmapData; 
    } 

Функция, которая разблокирует bitnapData:

public static void UnlockData(Bitmap bitmap, BitmapData bitmapData) 
    { 
     bitmap.UnlockBits(bitmapData); 
    } 

Функция, которая изменяет яркость изображения:

public static void Bright(int bright, BitmapData bitmapData, BackgroundWorker worker, DoWorkEventArgs e) 
    { 
     byte nPixelFormat = 0; 
     if (bitmapData.PixelFormat == PixelFormat.Format24bppRgb) nPixelFormat = 3; 
     else if (bitmapData.PixelFormat == PixelFormat.Format32bppArgb) nPixelFormat = 4; 

     int max = bitmapData.Height - 1; 
     int percent = 0; 

     unsafe 
     { 
      for (int y = 0; y < bitmapData.Height; y++) 
      { 
       byte* pBmpRow = (byte*)(bitmapData.Scan0 + y * bitmapData.Stride); 

       for (int x = 0; x < bitmapData.Width; x++) 
       { 
        if (worker.CancellationPending) 
        { 
         e.Cancel = true; 
         return; 
        } 
        int bVal = pBmpRow[nPixelFormat * x] + bright; 
        int gVal = pBmpRow[nPixelFormat * x + 1] + bright; 
        int rVal = pBmpRow[nPixelFormat * x + 2] + bright; 



        Clamp(ref bVal); 
        Clamp(ref gVal); 
        Clamp(ref rVal); 


        pBmpRow[nPixelFormat * x] = (byte)bVal; 
        pBmpRow[nPixelFormat * x + 1] = (byte)gVal; 
        pBmpRow[nPixelFormat * x + 2] = (byte)rVal; 
       } 
       //System.Threading.Thread.Sleep(5); 
       int curPercent = (y * 100)/max; 

       if (curPercent > percent) 
       { 
        percent = curPercent; 
        worker.ReportProgress(percent); 
       } 
      } 
     } 
    } 

В этой функции я проверяю отмену и обновление работы backgroundWorker.

Теперь у меня есть w trackbar и numericBox, которые я использую для изменения яркости. Когда значение трекбара или numericBox изменяется, запускается backgroundWorker. Проблема в том, что, когда backgroundWorker занят, и я изменил trackbarValue, backgroundWorker должен остановиться и начать заново. Теперь в моем коде работает кнопка liku. Когда рабочий занят, изменение значения останавливает работника, затем начинается его изменение.

Код:

private void OnNumericBoxValueChanged(object sender, EventArgs e) 
    { 


     m_trkBarBright.Value = (int)m_numericBright.Value; 

     brightValue = m_trkBarBright.Value; 
     if (backgroundWorker.IsBusy) 
     { 
      backgroundWorker.CancelAsync(); 
     } 
     else 
     { 
      backgroundWorker.RunWorkerAsync(); 
     } 


     m_btnOK.Focus(); 
    } 


    private void WorkerDoWork(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker worker = (BackgroundWorker)sender; 


     Colors.CopyImgData(m_orgImage, m_tempImage); 
     data = Colors.LockData(m_tempImage); 

     Colors.Bright(brightValue, data,worker, e); 

    } 

    private void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     if (e.Error != null) 
     { 
      Colors.UnlockData(m_tempImage, data); 
      MessageBox.Show(e.Error.Message); 
      progressBar1.Value = 0; 

     } 
     else if (e.Cancelled) 
     { 
      Colors.UnlockData(m_tempImage, data); 
      if(!exit) 
      m_imgBox.UpdateImage(m_tempImage); 
      MessageBox.Show("Canceled"); 
      progressBar1.Value = 0; 

     } 
     else 
     { 
      Colors.UnlockData(m_tempImage, data); 
      if (!exit) 
      m_imgBox.UpdateImage(m_tempImage); 
      progressBar1.Value = 0; 
      MessageBox.Show("Done"); 

     } 
    } 

    private void WorkerProgress(object sender, ProgressChangedEventArgs e) 
    { 
     progressBar1.Value = e.ProgressPercentage; 
    } 

Кто-нибудь имеет какие-либо идеи, как решить эту проблему?

ответ

0

Правильный способ сделать это: проверить backgroundWorker.CancellationPending и установить e.Cancel = true с WorkerDoWork.

CancelAsync не останавливает работника, он просто посылает сообщение в тему, говорящее «Я хотел бы остановиться».

Адрес full sample.