0

I am using How do I get an animated gif to work in WPF? in my program.

Initially in XAML, I set Visibility="Hidden" and

use animateImage.Visibility = Visibility.Visible; when I want the image to display.

After dispalying the image, I run a process. However, as soon as the process starts, the animation pauses. I wonder why is it doing that?

I was thinking to create a new thread and run GIF in the thread, and close the thread when process is completed.

EDIT

Code for the process that I am running. I want the animation to play during the GPUpdate.

ExecProc("gpupdate", "/force");

private static bool ExecProc(string file, string arg)
{
    bool flag = true;
    try
    {
        //Create a new process info structure.
        ProcessStartInfo pInfo = new ProcessStartInfo();
        pInfo.FileName = file;
        pInfo.CreateNoWindow = true;
        pInfo.Arguments = arg;
        pInfo.WindowStyle = ProcessWindowStyle.Hidden;

        Process ps = new Process();
        ps.StartInfo = pInfo;
        ps.Start();

        //Wait for the process to end.
        ps.WaitForExit();
    }
    catch (Exception e)
    {
        writeLog("Error: " + e + " running " + file + " " + arg);
        flag = false;
    }
    return flag;
}
Community
  • 1
  • 1
Imsa
  • 1,105
  • 2
  • 17
  • 39
  • You need to post more code. It's likely your process is blocking the UI thread and keeping the GIF from playing, but you haven't given enough details to say for sure. – Sean Beanland Apr 08 '16 at 18:07
  • @WasGoodDone all of the code is the link in the question. All I do is make it hidden or visible properties in my program. What other code are you referring to in addition to above? Thanks – Imsa Apr 08 '16 at 18:09
  • You say "I run a process." Your logic for this process is relevant to the problem you're having, thus it would be helpful to have that code as part of your question. http://stackoverflow.com/help/how-to-ask – Sean Beanland Apr 08 '16 at 18:12
  • @WasGoodDone I updated the question. – Imsa Apr 08 '16 at 18:16

2 Answers2

1

Here is the problem:

//Wait for the process to end.
ps.WaitForExit();

You are blocking the UI thread, waiting for the process to finish.

If you need to be informed when the process finishes, do that in another thread, and then invoke a callback on the UI thread:

var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
animateImage.Visibility = Visibility.Visible;
Task.Run(() =>
    {
        // Start the process and wait for it to finish, as you did before.
    }).ContinueWith(task =>
    {
        animateImage.Visibility = Visibility.Hidden;
        // Do whatever you need to do when the process is finished.
    }, uiScheduler);

Task.Run fires a thread and performs the task in that thread (it actually uses the thread pool, and does not create a new thread). ContinueWith does the same thing, but starts the task after the previous task has finished.

TaskScheduler.FromCurrentSynchronizationContext() captures the synchronization context from the main thread. Passing that synchronization context to ContinueWith, causes it to fire the task in the main (UI) thread, which is required when you are manipulating UI controls.

You can use several ContinueWiths to chain many tasks, so they run one after another. Just pass the captured synchronization context to the last one, which sets the animation visibility.

Mohammad Dehghan
  • 17,853
  • 3
  • 55
  • 72
  • I want animateImage to be visible for each process I run. So, process goes in the first `{ }` and `Visibility.Visible` to be in 2nd `{ }'. Thanks – Imsa Apr 08 '16 at 21:19
  • or if you could update the code with my code above, that would be great. – Imsa Apr 08 '16 at 21:40
  • @Imsa Yes. Try it and tell me the result. – Mohammad Dehghan Apr 10 '16 at 04:23
  • I get the following error: `The calling thread cannot access this object because a different thread owns it.` – Imsa Apr 15 '16 at 20:25
  • @Imsa Make sure you did everything like the code sample above. If it didn't work, post your code here, so I can take a look. – Mohammad Dehghan Apr 16 '16 at 13:31
  • Sorry! I updated the answer. Changing the vIsibility of the image should be done in main thread. – Mohammad Dehghan Apr 20 '16 at 14:35
  • It does not seem like it's working. I use the debugger, but it just skips over `Task.Run(() => ...`? – Imsa Apr 20 '16 at 17:04
  • It is the correct behavior. The anonymous method in the `Run` will run asynchronously, in another thread. Put a breakpoint inside the `Run`, to see what happens. – Mohammad Dehghan Apr 20 '16 at 17:46
  • Yup, it is working. Thanks. Now, I am trying to run Edit #3 ( updated code). Is that do able because it seems like it's not running as it's writing to logfile. – Imsa Apr 21 '16 at 16:11
  • I've a next button which is disabled before any process starts. I enable it after all processes are done. how can I keep track of all of task and then enable the button again? – Imsa Apr 21 '16 at 16:35
1

Mohammad Dehghan was really helpful and got me in the right direction. However, I was looking something slightly different, so posting what ended up with.

It goes and executes the process while other stuff is keep running in the background.

animateImage.Visibility = Visibility.Visible;
    await Task.Run(() =>
    {
        // Process goes here
    });
animateImage.Visibility = Visibility.Hidden;
Imsa
  • 1,105
  • 2
  • 17
  • 39