0

I have a program I wrote in C# with a window.

I have a button that do some things (it doesn't matter what exactly) and it refresh the window in his loop (in button_click function) (with this.Invalidate(false); (I don't use this.Refresh because I have a groupBox that I don't want to refresh)).

I cant minimize the window while the button_click function working. there is something I can do to solve it?

**lets say I have this code:

    void button_click(object sender, EventArgs e)
    {
        progressBar1.Value = 0;
        progressBar1.Maximum = int.Parse(somelabel_num.Text);
        int i;
        OpenFileDialog file = new OpenFileDialog();
        file.ShowDialog();
        if (file.FileName == "")
            return;
        this.Refresh();
        Bitmap image = new Bitmap(file.FileName);
        groupBox1.BackgroundImage = image;

        for (i = 0; i < int.Parse(somelabel_num.Text); i++)
        {
            this.Text = i;
            this.Invalidate(false);
            progressBar1.PerformStep();
        }
    }

so how to do this as a thread that gets the paremeters?

George
  • 85
  • 1
  • 1
  • 7

2 Answers2

1

As already suggested, you should consider running button task in one of many ways you can in .NET (Thread, ThreadPool, Task etc).

However, if you are looking for a quick fix you can try one of these things:

  1. Call Application.DoEvents() to allow UI to process window message pump. e.g.

    WindowState = FormWindowState.Minimized;
    Application.DoEvents();
    
  2. Call minimization asynchronously e.g.

    if (InvokeRequired)
        BeginInvoke(
            new Action(() => WindowState = FormWindowState.Minimized)
        );
    
Nikola Radosavljević
  • 6,871
  • 32
  • 44
0

Better way is to run the code at your button in another thread so it will not block the UI when you press the button.

Edit: Code sample from my other answer:

private readonly object _userActivityLocker = new object();

private void button1_Click(object sender, EventArgs e)
{
    new Thread(delegate()
    {
    if (System.Threading.Monitor.TryEnter(_userActivityLocker))
    {
        //note that any sub clicks will be ignored while we are here
        try
        {
            //here execute your long running operation without blocking the UI
        }
        finally
        {
            System.Threading.Monitor.Exit(_userActivityLocker);
        }
    }
    }) { IsBackground = true }.Start();
}

Edit: You stated at comment that

exception is occurs when the code reaches to an openFileDialog call). I get this exeption: System.Threading.ThreadStateException

You need to invoke the OpenFileDialog code in the form main thread. so inside the try block:

this.Invoke(new Action(() =>
{
    using (OpenFileDialog dialog = new OpenFileDialog())
    {
        if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            Console.WriteLine(dialog.FileName);
        }
    }
}));

Also check this.

Edit2: After seeing your question code updated, I will advice you to use BackgroundWorker instead.

Community
  • 1
  • 1
Jalal Said
  • 15,906
  • 7
  • 45
  • 68
  • I tried that and it seems that it have some problem (is occurs when the code reaches to an openFileDialog call). I get this exeption: System.Threading.ThreadStateException: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. – George Jul 16 '11 at 01:32
  • @George: if you are calling or using UI controls, you should `Invoke` the UI methods or properties in the UI thread.. For more information check [this](http://stackoverflow.com/questions/6556330/threading-cross-threading-in-c-net-how-do-i-change-combobox-data-from-another/6556401#6556401) – Jalal Said Jul 16 '11 at 01:36
  • this is making problems. perhaps, passing variables to the thread will help. how do I do that? – George Jul 16 '11 at 02:02
  • maybe there is a simpler way that I can pass parameters to the thread? The openFileDialog is not the only problem - after putting this part in a "/**/", there art still problems concerning variables that dont belongs to this thread. – George Jul 16 '11 at 02:06
  • @George: I need a little more code to diagnose the problem. Also note that you need to invoke whenever you are accessing a UI components like `TextBox` or `Button` from another thread... – Jalal Said Jul 16 '11 at 02:12
  • can you show me how to involve the backgroundWorker with my code? – George Jul 16 '11 at 03:24
  • @George: Read that article and other articles about `BackgroundWorker`, play with it a little bit and try to use it, I only show you the path, you are the one that should pass through it :) – Jalal Said Jul 16 '11 at 03:38