Check Process state in an GUI app

View: New views
8 Messages — Rating Filter:   Alert me  

Check Process state in an GUI app

by hellboy195 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

hi,
I'm currently trying to write a very very simple front-end for ffmpeg with gtk#.
My Code looks like this:

First I check if a file already exits with File.Exits(path)
MessageDialog -> Overwrite YesNO.

Then the I start ffmpeg with Process.Start().
Then I want show a MessageDialog if the process finished so I did it like :

while(!proc.HasExited) {}
MessageDialog -> "Encoding finished";

This is working good but this causes some bugs. E.g: If I do Overwrite it "yes". The MessageDialog isn't destroyed until the process finished. If I delete this while {} it's working correct but the Message appears immediately and not after the process hast Finished. Using if is also not that good I suppose :/

Any solution? Thx in advance :)

Re: Check Process state in an GUI app

by Michael Hutchinson :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Jan 21, 2008 11:58 AM, hellboy195 <hellboy195@...> wrote:

>
> hi,
> I'm currently trying to write a very very simple front-end for ffmpeg with
> gtk#.
> My Code looks like this:
>
> First I check if a file already exits with File.Exits(path)
> MessageDialog -> Overwrite YesNO.
>
> Then the I start ffmpeg with Process.Start().
> Then I want show a MessageDialog if the process finished so I did it like :
>
> while(!proc.HasExited) {}
> MessageDialog -> "Encoding finished";
>
> This is working good but this causes some bugs. E.g: If I do Overwrite it
> "yes". The MessageDialog isn't destroyed until the process finished. If I
> delete this while {} it's working correct but the Message appears
> immediately and not after the process hast Finished. Using if is also not
> that good I suppose :/
>
> Any solution? Thx in advance :)

Your loop is hanging the GUI thread, by not allowing GTK to return to
its main loop (in which it does all the drawing etc).

Handle the Process.Exited thread instead:

proc.Exited += delegate {
    MessageDialog -> "Encoding finished";
};

--
Michael Hutchinson
http://mjhutchinson.com
_______________________________________________
Gtk-sharp-list maillist  -  Gtk-sharp-list@...
http://lists.ximian.com/mailman/listinfo/gtk-sharp-list

Re: Check Process state in an GUI app

by hellboy195 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Michael Hutchinson wrote:
On Jan 21, 2008 11:58 AM, hellboy195 <hellboy195@gmail.com> wrote:
>
> hi,
> I'm currently trying to write a very very simple front-end for ffmpeg with
> gtk#.
> My Code looks like this:
>
> First I check if a file already exits with File.Exits(path)
> MessageDialog -> Overwrite YesNO.
>
> Then the I start ffmpeg with Process.Start().
> Then I want show a MessageDialog if the process finished so I did it like :
>
> while(!proc.HasExited) {}
> MessageDialog -> "Encoding finished";
>
> This is working good but this causes some bugs. E.g: If I do Overwrite it
> "yes". The MessageDialog isn't destroyed until the process finished. If I
> delete this while {} it's working correct but the Message appears
> immediately and not after the process hast Finished. Using if is also not
> that good I suppose :/
>
> Any solution? Thx in advance :)

Your loop is hanging the GUI thread, by not allowing GTK to return to
its main loop (in which it does all the drawing etc).

Handle the Process.Exited thread instead:

proc.Exited += delegate {
    MessageDialog -> "Encoding finished";
};

--
Michael Hutchinson
http://mjhutchinson.com
_______________________________________________
Gtk-sharp-list maillist  -  Gtk-sharp-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/gtk-sharp-list
Hi,
thank you very much for your help. I tried both of you methods and it's working really great but there is one thing left that should work. With my old (buggy) version the Files from the Treeview were removed automatically when the encoding was finshed. That means. I have a treeview with let's say 3 titels and after the first title is finished with encoding it should be removed to only 2 are remaining and so on ...
Any chance that I can manage it like in the past with?

                this.menuListStore.GetIterFirst(out iter);
                this.menuListStore.Remove(ref iter);


Parent Message unknown Re: Check Process state in an GUI app

by Chris Howie :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

(Oops, sent this to the wrong list.)

On Jan 21, 2008 12:45 PM, Chris Howie <cdhowie@...> wrote:

> On Jan 21, 2008 11:58 AM, hellboy195 <hellboy195@...> wrote:
> > hi,
> > I'm currently trying to write a very very simple front-end for ffmpeg with
> > gtk#.
> > My Code looks like this:
> >
> > First I check if a file already exits with File.Exits(path)
> > MessageDialog -> Overwrite YesNO.
> >
> > Then the I start ffmpeg with Process.Start().
> > Then I want show a MessageDialog if the process finished so I did it like :
> >
> > while(!proc.HasExited) {}
> > MessageDialog -> "Encoding finished";
> >
> > This is working good but this causes some bugs. E.g: If I do Overwrite it
> > "yes". The MessageDialog isn't destroyed until the process finished. If I
> > delete this while {} it's working correct but the Message appears
> > immediately and not after the process hast Finished. Using if is also not
> > that good I suppose :/
> >
> > Any solution? Thx in advance :)
>
> The problem is that you are waiting for the operation to complete on
> the GUI thread.  You have destroyed the dialog, but Gtk cannot
> actually remove the dialog from the screen until you give control back
> to the main GUI loop.
>
> What you want to do is either add an idle handler or spin off another
> thread to take care of it.  An idle handler would probably be easiest
> for your purpose:
>
> // Message dialog code
> Process proc = ...;
> GLib.Idle.Add(delegate {
>     if (proc.HasExited) {
>         // Show dialog.
>         return false; // Remove this delegate from the idle list.
>     }
>
>     return true; // Run this delegate again when idle.
> });
>
> Note that this approach can burn quite a bit of CPU running the idle
> delegate.  You may want to try attaching an event handler to
> Process.Exited instead:
>
> proc.EnableRaisingEvents = true;
> proc.Exited += delegate {
>     Application.Invoke(delegate {
>         // Show dialog.
>     });
> };
>
> Note that you must call Application.Invoke because the Exited event
> handler will not be running on the GUI thread, and you should not
> touch the GUI from other threads.  Application.Invoke puts a delegate
> in a queue to be executed on the GUI thread the next time the main
> loop is entered.

--
Chris Howie
http://www.chrishowie.com
http://en.wikipedia.org/wiki/User:Crazycomputers
_______________________________________________
Gtk-sharp-list maillist  -  Gtk-sharp-list@...
http://lists.ximian.com/mailman/listinfo/gtk-sharp-list

Re: Check Process state in an GUI app

by Chris Howie :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Jan 21, 2008 1:26 PM, hellboy195 <hellboy195@...> wrote:

> Hi,
> thank you very much for your help. I tried both of you methods and it's
> working really great but there is one thing left I that should work. With my
> old (buggy) version the Files from the Treeview were removed automatically
> when the encoding was finshed. That means. I have a treeview with let's say
> 3 titels and after the first title is finished with encoding it should be
> removed to only 2 are remaining and so on ...
> Any chance that I can manage it like in the past with?
>
>                 this.menuListStore.GetIterFirst(out iter);
>                 this.menuListStore.Remove(ref iter);

You still can, you just need to do this from the GUI thread.  We will
need more information about the circumstances you are doing this under
to help.  Can you paste your code?

--
Chris Howie
http://www.chrishowie.com
http://en.wikipedia.org/wiki/User:Crazycomputers
_______________________________________________
Gtk-sharp-list maillist  -  Gtk-sharp-list@...
http://lists.ximian.com/mailman/listinfo/gtk-sharp-list

Re: Check Process state in an GUI app

by hellboy195 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Chris Howie-3 wrote:
On Jan 21, 2008 1:26 PM, hellboy195 <hellboy195@gmail.com> wrote:
> Hi,
> thank you very much for your help. I tried both of you methods and it's
> working really great but there is one thing left I that should work. With my
> old (buggy) version the Files from the Treeview were removed automatically
> when the encoding was finshed. That means. I have a treeview with let's say
> 3 titels and after the first title is finished with encoding it should be
> removed to only 2 are remaining and so on ...
> Any chance that I can manage it like in the past with?
>
>                 this.menuListStore.GetIterFirst(out iter);
>                 this.menuListStore.Remove(ref iter);

You still can, you just need to do this from the GUI thread.  We will
need more information about the circumstances you are doing this under
to help.  Can you paste your code?

--
Chris Howie
http://www.chrishowie.com
http://en.wikipedia.org/wiki/User:Crazycomputers
_______________________________________________
Gtk-sharp-list maillist  -  Gtk-sharp-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/gtk-sharp-list
Sure, no problem. Though I don't know if I should post the whole one ore not ^^. anyway. here it is :

        protected virtual void OnCovertClicked (object sender, System.EventArgs e)
        {
                try
                {
                this.SelectFolder.Sensitive = false;
                this.FileAdd.Sensitive = false;
            this.RemoveFile.Sensitive = false;
                this.ClearAll.Sensitive = false;
                this.entry1.Sensitive = false;
                this.combobox1.Sensitive = false;
                this.combobox2.Sensitive = false;
                this.menubar1.Sensitive = false;
                       
                selectedFile = String.Empty;
                newselectedFile = String.Empty;
                oldselectedFile = String.Empty;

                while(this.menuListStore.GetIterFirst(out iter) != false)
                {
                format = this.combobox1.ActiveText;
                quality = this.combobox2.ActiveText;
                iter = new TreeIter();
               
                menuListStore.GetIterFirst(out iter);
                selectedFile = (string)menuListStore.GetValue(iter, 0);
               
                if(selectedFile.Substring(selectedFile.Length -4) == "flac") number+=1;
                               
                oldselectedFile = selectedFile.Replace(selectedFile.Substring(selectedFile.Length - number), format);
                selectedFile = selectedFile.Replace(" ", "\\ ");
                newselectedFile = selectedFile.Replace(selectedFile.Substring(selectedFile.Length - number), format);
                               
                if(selectedFile.Substring(selectedFile.Length -4) == "flac") number-=1;
               
                string command = "ffmpeg -y -i " + selectedFile + " -ab " + quality.Replace("b/s", " ") + newselectedFile;
                                       
                if (System.IO.File.Exists(oldselectedFile))
            {
                        MessageDialog md = new MessageDialog (this,
                                                      DialogFlags.DestroyWithParent,
                                   MessageType.Question,
                                      ButtonsType.YesNo, newselectedFile + " already exits. Overwrite it?");
                       
                        ResponseType result = (ResponseType)md.Run ();
                       
                        if (result == ResponseType.Yes)
                        {
                        md.Destroy();
                        this.Convert.Sensitive = false;
                        proc = Process.Start(command);
                        }
                        else
                        {
                        this.FileAdd.Sensitive = true;
                        this.Convert.Sensitive = false;
                        md.Destroy();
                        }
                }
                else
                {
                this.Convert.Sensitive = false;
                proc = Process.Start(command);
                }
                this.menuListStore.GetIterFirst(out iter);
                this.menuListStore.Remove(ref iter);

                }
// GLib.Idle.Add(delegate {
// if (proc.HasExited) {
//
// MessageDialog mdg = new MessageDialog(this, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Ok, "Encoding finished");
// mdg.Run();
// mdg.Destroy();
//        
//        return false; // Remove this delegate from the idle list.
//    }
//
//    return true; // Run this delegate again when idle.
//});
                proc.EnableRaisingEvents = true;
                        proc.Exited += delegate {
                                Application.Invoke(delegate {
        MessageDialog mdg = new MessageDialog(this, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Ok, "Encoding finished");
                mdg.Run();
                mdg.Destroy();
    });
};

                       
                this.FileAdd.Sensitive = true;
                this.Convert.Sensitive = false;
                this.SelectFolder.Sensitive = true;
                this.entry1.Sensitive = true;
                this.combobox1.Sensitive = true;
                this.combobox2.Sensitive = true;
                this.menubar1.Sensitive = true;
                       
        }
                catch(Exception ee)
                {
                        Console.WriteLine(ee);
                }
        }


In my eyes it's very ugly code and beside my problem here I would appreciate any suggestions ;)
Thx :D

Re: Check Process state in an GUI app

by Chris Howie :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Jan 21, 2008 2:34 PM, hellboy195 <hellboy195@...> wrote:
> Sure, no problem. Though I don't know if I should post the whole one ore not
> ^^. anyway. here it is :
>
> [snip]
>
> In my eyes it's very ugly code and beside my problem here I would appreciate
> any suggestions ;)
> Thx :D

Thanks, that helped a lot.

Basically, you are going to have to change your entire code flow and
break it apart a bit.  You are going to need one method that is
responsible for checking your preconditions (popping a dialog to
confirm, etc) and starting the process on one file.  Then in the
Exited handler you need to start the process on the next file.  So
something like this pseudo-code:

OnConvertClicked():
    ProcessNextFile();

ProcessNextFile():
    CheckPreconditions;
    StartProcess;
    AttachEventHandler -> Application.Invoke -> OnProcessCompleted;

OnProcessCompleted():
    RemoveProcessedFileFromList;
    If MoreFilesToProcess
        ProcessNextFile();

Something like that.  You may want to make your window insensitive
during the processing too, or at least any buttons that can change the
state of your application.  You don't want people modifying the file
list while you are processing, for example.

--
Chris Howie
http://www.chrishowie.com
http://en.wikipedia.org/wiki/User:Crazycomputers
_______________________________________________
Gtk-sharp-list maillist  -  Gtk-sharp-list@...
http://lists.ximian.com/mailman/listinfo/gtk-sharp-list

Re: Check Process state in an GUI app

by hellboy195 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Chris Howie-3 wrote:
On Jan 21, 2008 2:34 PM, hellboy195 <hellboy195@gmail.com> wrote:
> Sure, no problem. Though I don't know if I should post the whole one ore not
> ^^. anyway. here it is :
>
> [snip]
>
> In my eyes it's very ugly code and beside my problem here I would appreciate
> any suggestions ;)
> Thx :D

Thanks, that helped a lot.

Basically, you are going to have to change your entire code flow and
break it apart a bit.  You are going to need one method that is
responsible for checking your preconditions (popping a dialog to
confirm, etc) and starting the process on one file.  Then in the
Exited handler you need to start the process on the next file.  So
something like this pseudo-code:

OnConvertClicked():
    ProcessNextFile();

ProcessNextFile():
    CheckPreconditions;
    StartProcess;
    AttachEventHandler -> Application.Invoke -> OnProcessCompleted;

OnProcessCompleted():
    RemoveProcessedFileFromList;
    If MoreFilesToProcess
        ProcessNextFile();

Something like that.  You may want to make your window insensitive
during the processing too, or at least any buttons that can change the
state of your application.  You don't want people modifying the file
list while you are processing, for example.

--
Chris Howie
http://www.chrishowie.com
http://en.wikipedia.org/wiki/User:Crazycomputers
_______________________________________________
Gtk-sharp-list maillist  -  Gtk-sharp-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/gtk-sharp-list
You are helping me a lot. Thank you very much. Yeah as you can see I already tried to set all buttons,.. insensetive. Thx for you posted solution but I'm totally new to this. Can you give me a more specific code? Unfortunately the docs are really really *unfilled* I wouldn't ask