如何用线程中的图片框来解决我的问题? [英] How to fiqure out my problem with picture box in thread?

查看:68
本文介绍了如何用线程中的图片框来解决我的问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我正在编写一个程序(学术项目),它读取一个5000000元素的文本文件,并通过合并排序,快速排序和交换排序,通过线程对其进行排序,并且以图形方式显示进度。

我只编写了合并排序,但在使用线程时显示进度存在问题!

为了显示进度,我用一个图片框来制作自定义进度条,但它不起作用。顺便说一句,它没有线程,没有任何问题!

我需要使用图片框显示进度!

现在,我怎么能弄明白?



有人帮帮我吧!



在此先感谢。



和代码:

Hi,
I''m writing a program(academic project) which reads a 5000000-element-text-file and sorts it by merge sort, quick sort and exchange sort, by threading, and showing the progresses graphically.
I''ve only written merge sort, but there is a problem in showing the progress when I use thread!
For showing the progress, I used a picture box to make a custom progress bar, but it doesn''t work. By the way, it works without thread and doesn''t have any problem!
I need to show the progress by using a picture box!
Now, how can I figure this out??

somebody help me, please!

Thanks in advance.

And the code:

public int[] arr1;
private void button1_Click(object sender, EventArgs e)
{
    if (InitializingData())
    {
        label1.Visible = true;
        Thread t1 = new Thread(delegate() { MergeSort(arr1); });
        t1.Start();
    }
}

private bool InitializingData()
{
    if (!File.Exists(Application.StartupPath + @"\input.txt"))
    {
        MessageBox.Show("The input file was not found!");
        return false;
    }
    try
    {
        #region Reading input file as a string array, and reserving space for input data
        StreamReader objFileReader = new StreamReader(Application.StartupPath + @"\input.txt");
        string[] str = objFileReader.ReadLine().Split(',');
        objFileReader.Dispose();
        arr1 = new int[str.Length];
        arr2 = new int[str.Length];
        arr3 = new int[str.Length];
        MessageBox.Show("The usage space was reserved successfully!!!");
        #endregion

        #region Putting input elements from the string array to integer array
        int cnt = 0;
        foreach (string obj in str)
        {
            arr1[cnt] = int.Parse(obj);
            arr2[cnt] = int.Parse(obj);
            arr3[cnt++] = int.Parse(obj);
        }
        MessageBox.Show("The input data initialized successfully!!!");
        #endregion
    }
    catch
    {
        MessageBox.Show("Wrong input!!!");
        return false;
    }
    return true;
}

#region Merge Sort...
private void MergeSort(int[] l_arr)
{
    int h = l_arr.Length / 2;
    int m = l_arr.Length - h;
    int[] left = new int[h];
    int[] right = new int[m];
    if (l_arr.Length > 1)
    {
        for (int i = 0; i < h; i++)
            left[i] = l_arr[i];
        for (int i = h, j = 0; i < l_arr.Length; i++, j++)
            right[j] = l_arr[i];

        MergeSort(left);
        MergeSort(right);
        Merge(left, right, l_arr);
    }
}

private void Merge(int[] left, int[] right, int[] l_arr)
{
    int arrIndex, leftIndex, rightIndex;
    arrIndex = leftIndex = rightIndex = 0;
    while (leftIndex < left.Length && rightIndex < right.Length)
    {
        if (left[leftIndex] < right[rightIndex])
            l_arr[arrIndex++] = left[leftIndex++];
        else
            l_arr[arrIndex++] = right[rightIndex++];
    }
    while (leftIndex < left.Length)
        l_arr[arrIndex++] = left[leftIndex++];
    while (rightIndex < right.Length)
        l_arr[arrIndex++] = right[rightIndex++];
    ShowProgressBar(pictureBox1, arr1.Length);
}
#endregion

#region Show progress bar
int cnt = 1;
private void ShowProgressBar(object sender, int max)
{
    PictureBox objProgressBar = (PictureBox)sender;
    Bitmap objBM = new Bitmap(objProgressBar.Width, objProgressBar.Height);
    Graphics objGraphic = Graphics.FromImage(objBM);
    objGraphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
    objGraphic.FillRectangle(Brushes.Violet, new Rectangle(0, 0, ((cnt++) * objProgressBar.Width) / max, objProgressBar.Height));
    try { objProgressBar.Image = objBM; }
    catch { }
    Application.DoEvents();
}
#endregion



- -----------------------



我已将ShowProgressBar更改为:


-------------------------

I''ve changed ShowProgressBar to this:

int cnt = 1;
        private void ShowProgressBar(object sender, int max)
        {
            
            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(delegate { ShowProgressBar(sender, max); }));
            }
            else
            {
                PictureBox objProgressBar = (PictureBox)sender;
                Bitmap objBM = new Bitmap(objProgressBar.Width, objProgressBar.Height);
                Graphics objGraphic = Graphics.FromImage(objBM);
                objGraphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                objGraphic.FillRectangle(Brushes.Violet, new Rectangle(0, 0, ((cnt++) * objProgressBar.Width) / max, objProgressBar.Height));
                objProgressBar.Image = objBM;
                this.Text = (((cnt) * 100) / max).ToString() + '%';
            }
        }



------------------------ < br $>


QuickSort方法:


------------------------

The QuickSort method:

#region Quick Sort
        int pivotpoint;
        void QuickSort(int low, int high, int[] l_arr)
        {
            pivotpoint=low;
            if (high > low)
            {
                partition(low, high, l_arr);
                QuickSort(low, pivotpoint - 1, l_arr);
                QuickSort(pivotpoint + 1, high, l_arr);
            }
        }
        void partition(int low, int high, int[] l_arr)
        {
            int i, j;//, pivotpoint;
            int tmp;
            int pivotitem = l_arr[low];
            j = low;
            for (i = low + 1; i <= high; i++)
            {
                if (l_arr[i] < pivotitem)
                {
                    j++;
                    tmp = l_arr[i];
                    l_arr[i] = l_arr[j];
                    l_arr[j] = tmp;
                }
            }
            pivotpoint = j;
            tmp = l_arr[low];
            l_arr[low] = l_arr[pivotpoint];
            l_arr[pivotpoint] = tmp;
            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(delegate { partition(low, high, l_arr); }));
            }
            else
            {
                ShowProgressBar(pictureBox2, arr2.Length);
            }
        }
        #endregion

推荐答案

除了从创建它们的线程 - UI线程外,你不能访问控件。当你尝试时,你会看到一个错误。



使用P / Invoke更新你的图片框,或者从显式线程切换到BackgroundWorker其中包含内置的进度报告。

调用:

You can''t access Controls except from the thread they were created on - the UI thread. When you try, you get an error, as you have seen.

Either use P/Invoke to update your picture box, or switch from an explicit thread to a BackgroundWorker which has progress reporting built in.
Invoke:
private void ShowProgress(int percent)
    {
    if (InvokeRequired)
        {
        Invoke(new MethodInvoker(delegate { ShowProgress(percent); }));
        }
    else
        {
        ...
        }
    }





如果您在 BackgroundWorker类 [ ^ ]它给出了一个包含进度报告的例子。



但为了善良,请开始处理你的对象!位图和图形上下文都是稀缺资源,如果你只是在没有正确处理它们的情况下创建它们,那么在RAM耗尽之前就会出现Out of Memory错误!



并摆脱Application.DoEvents!你正在使用线程,你真的,真的,不希望它在那里!



If you look on MSDN under BackgroundWorker Class[^] it gives an example which includes progress reporting.

But for goodness sake start Disposing of your objects! Both Bitmaps and Graphics contexts are scarce resources, and if you just create them without correctly disposing them, you will get an "Out of Memory" error long before you run out of RAM!

And get rid of Application.DoEvents! You are using threading, you really, really, do not want that in there!


这篇关于如何用线程中的图片框来解决我的问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆