[ DarkMan @ 09.04.2010. 14:16 ] @
Imam sledeci kod:
Code (csharp):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.Run(new FormTest());
        }
    }

    public class FormTest: Form
    {
        public FormTest()
        {
            Button button1 = new Button();
            button1.Text = "Test 1";
            button1.Dock = DockStyle.Top;
            button1.Click += new EventHandler(button1_Click);
           
            Button button2 = new Button();
            button2.Text = "Test 2";
            button2.Dock = DockStyle.Top;
            button2.Click += new EventHandler(button2_Click);

            this.Controls.Add(button2);
            this.Controls.Add(button1);

            this.TopLevel = true;
            this.ClientSize = new System.Drawing.Size(100, 60);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (Helper.IsVisible) {
                Helper.Hide();
            } else {
                Helper.Show();
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {
            Helper.Show();
            long tick = Environment.TickCount;
            while ((Environment.TickCount - tick) < 2000) ;
            Helper.Hide();
        }
    }

    public class Helper
    {
        private static object padLock = new object();
        private static FormThread _form = null;
        private volatile static IAsyncResult asyncResult = null;

        private delegate void ShowFormDelegate();
        private static void ShowForm()
        {
            _form = new FormThread();
            _form.ShowDialog();
        }

       
        public static void Show()
        {
            lock (padLock) {
                if (_form != null) {
                    _form.SetVisible(true);
                } else {
                    //ShowFormDelegate showForm = new ShowFormDelegate(ShowForm);
                    //asyncResult = showForm.BeginInvoke(null, null);
                    System.Threading.Thread thread = new System.Threading.Thread(ShowForm);
                    thread.Start();
                }
            }
        }

        public static void Hide()
        {
            lock (padLock) {
                if (_form != null) _form.SetVisible(false);
            }
        }

        public static bool IsVisible
        {
            get { return (_form != null ? _form.Visible : false); }
        }
    }

    public class FormThread: Form
    {

        public FormThread()
        {
            ProgressBar bar = new ProgressBar();
            bar.Dock = DockStyle.Top;
            bar.Style = ProgressBarStyle.Marquee;
            this.Controls.Add(bar);
            this.TopLevel = true;
            this.ClientSize = bar.Size;
            this.StartPosition = FormStartPosition.CenterScreen;
            System.Diagnostics.Debug.WriteLine("Constructor thread: " + System.AppDomain.GetCurrentThreadId());
        }

        public void SetVisible(bool visible)
        {
            if (this.InvokeRequired) {
                System.Diagnostics.Debug.WriteLine("Ivoke required thread: " + System.AppDomain.GetCurrentThreadId());
                this.Invoke(new SetVisibleDelegate(SetVisible), visible);
                return;
            }
            this.Visible = visible;
            Application.DoEvents();
            System.Diagnostics.Debug.WriteLine("Set visible thread: " + System.AppDomain.GetCurrentThreadId());
        }
        delegate void SetVisibleDelegate(bool visible);
    }
}
 


Na prvoj formi ima dva dugmeta. Na prvo dugme se prikazuje/sakriva forma koja se kreira na drugom thread-u a na drugo dugme se prikaze ta ista forma, zatim se naredne dve sekunde vrti jedna while petlja koja simulira neku blokirajucu operaciju i na kraju se ta forma zatvara.

Kada koristimo drugo dugme za prikaz thread forme, marquee progress bar radi samo pri prvom koriscenju tj. kada se forma prvi put kreira. Po sledecem kliku na drugo digme taj marquee vise ne radi.
Problem je u metodi SetVisible koja treba da prikaze/sakrije tu formu na drugom threadu. Prvi put kada se izvrsava ta metoda u debugu je pravilno ispisano da je metoda pozvana iz drugog threada i da je potreban invoke. Nakon tog invoka u debugu se vidi da je Invoke pozvao metodu SetVisible u originalnom threadu kojim je forma i kreirana. Po drugom pozivanju metode SetVisible ovo vise ne radi kako je zamisljeno tj. Invoke vise nije potreban (InvokeRequired je false) a SetVisible se slobodno izvrsava u glavnom threadu. Ne razumem zasto se ovo desava a problem je to sto marquee vise ne radi kada se obavlja neka blokirajuca operacija jer ga je Invoke nekako prebacio u isti thread kao glavna forma.

Da li neko ima neko objasnjenje zasto se ovo desava i kako ovo resiti?

[Ovu poruku je menjao Shadowed dana 09.04.2010. u 17:20 GMT+1]
[ DarkMan @ 09.04.2010. 20:01 ] @
Ipak nisam dobro napisao thread. Nisam primetio da kada formu sakrijem thread se zavrsi. Uz malu doradu sve je proradilo kako sam hteo.

Code (csharp):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.Run(new FormTest());
        }
    }

    public class FormTest: Form
    {
        public FormTest()
        {
            Button button1 = new Button();
            button1.Text = "Test 1";
            button1.Dock = DockStyle.Top;
            button1.Click += new EventHandler(button1_Click);
           
            Button button2 = new Button();
            button2.Text = "Test 2";
            button2.Dock = DockStyle.Top;
            button2.Click += new EventHandler(button2_Click);

            this.Controls.Add(button2);
            this.Controls.Add(button1);

            this.TopLevel = true;
            this.ClientSize = new System.Drawing.Size(100, 60);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (Helper.IsVisible) {
                Helper.Hide();
            } else {
                Helper.Show();
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {
            Helper.Show();
            long tick = Environment.TickCount;
            while ((Environment.TickCount - tick) < 2000) ;
            Helper.Hide();
        }
    }

    public class Helper
    {
        private static object padLock = new object();
        private static FormThread _form = null;

        private delegate void ShowFormDelegate();
        private static void ShowForm()
        {
            _form = new FormThread();
            Application.Run(_form);
            System.Diagnostics.Debug.WriteLine("Thread exiting");
        }

       
        public static void Show()
        {
            lock (padLock) {
                if (_form != null) {
                    _form.SetVisible(true);
                } else {
                    System.Threading.Thread thread = new System.Threading.Thread(ShowForm);
                    thread.Start();
                    Application.ThreadExit += new EventHandler(Application_ThreadExit);
                }
            }
        }

        static void Application_ThreadExit(object sender, EventArgs e)
        {
            lock (padLock) {
                if (_form != null) {
                    System.Diagnostics.Debug.WriteLine("ThreadExit thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
                    _form.CloseForm();
                    _form = null;
                }
            }            
        }

        static void Application_ApplicationExit(object sender, EventArgs e)
        {
        }

        public static void Hide()
        {
            lock (padLock) {
                if (_form != null) _form.SetVisible(false);
            }
        }

        public static bool IsVisible
        {
            get { return (_form != null ? _form.Visible : false); }
        }
    }

    public class FormThread: Form
    {
        public FormThread()
        {
            ProgressBar bar = new ProgressBar();
            bar.Dock = DockStyle.Top;
            bar.Style = ProgressBarStyle.Marquee;
            this.Controls.Add(bar);
            this.TopLevel = true;
            this.ClientSize = bar.Size;
            this.StartPosition = FormStartPosition.CenterScreen;

            System.Diagnostics.Debug.WriteLine("Constructor thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        }

        public void SetVisible(bool visible)
        {
            if (this.InvokeRequired) {
                System.Diagnostics.Debug.WriteLine("Ivoke required thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
                this.Invoke(new SetVisibleDelegate(SetVisible), visible);
                return;
            }
            this.Visible = visible;
            Application.DoEvents();
            System.Diagnostics.Debug.WriteLine("Set visible thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        }
        delegate void SetVisibleDelegate(bool visible);

        public void CloseForm()
        {
            if(this.InvokeRequired) {
                System.Diagnostics.Debug.WriteLine("Ivoke required thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
                this.Invoke(new MethodInvoker(CloseForm));
                return;
            }
            this.Close();
            this.Dispose();
            System.Diagnostics.Debug.WriteLine("Close form thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        }
    }
}