1

Ok so I have a WPF application which on button press runs through a list of tests like this:

  1. RunTest button pressed in GUI
  2. BackgroundWorker is created and starts running DoWork (see below):
  3. When t.Name == "TestSpecial" I want to show an image in the UI before I proceed. It's crucial that the image is showing before I continue.

    DoWork(...)
    {
        List<Test> tests = ....
    
        for (Test t in tests)
        {
            switch(t.Name)
            {
                case "Test1":
                    //Do something
                    break;
                case "Test2":
                    //Do something else 
                    break;
                ...
                case "TestSpecial":
                    // Here I want to:
                    // 1. Tell UI to show an image on the screen
                    // 2. Wait for the image to show up
                    // 3. Continue with my test
                    break;
                case "TestN+1":
                    //Do something completly different
                    break;
            }
        }
    }
    

I could probably use the Dispatcher.InvokeAsync or similar to get the image to show but is there any way to wait for it to finish or in some other way garantuee that the image is showing before proceeding?

Sheridan
  • 68,826
  • 24
  • 143
  • 183
patrick.elmquist
  • 2,113
  • 2
  • 21
  • 35
  • Why not use an actual UI testing framework like Coded UI? – Daniel Mann Jan 20 '14 at 15:54
  • You could run all your tests in background, showing progress and with cancel possibility. This way waiting for something is not a problem. Otherwise you have somehow to stop your tests (exit `DoWork` completely) and continue (enter it again) only after image is shown (event?). – Sinatr Jan 20 '14 at 15:58
  • Check [Event wait handles](http://msdn.microsoft.com/en-us/library/ksb7zs2x(v=vs.110).aspx) – Bolu Jan 20 '14 at 16:02
  • @ DanielMann In this case it's not about testing the UI, the application itself is testing hardware using cameras. @ Bolu Thx, will look in to that. – patrick.elmquist Jan 20 '14 at 16:12
  • How do you know when “the image is showing”? – Dour High Arch Jan 20 '14 at 17:35
  • How strict is showing? Is this an image that can take a long time to paint or are you good with continuing as soon as the image is sent to the UI? – paparazzo Jan 20 '14 at 18:26
  • The best thing would be to be garantueed that the image is visually showing. The thing about SpecialTest is that it uses cameras to take pictures of the screen when the image is showing. This means that there could become problems if the image is a little bit delayed, showing up in the middle of the camera taking a picture. In 99% of the times there will probably not be a delay and it will just work fine without any fix but since this will be used 10-100 thousand times I'd like to minimize the risk. – patrick.elmquist Jan 21 '14 at 10:44

3 Answers3

0

I think that if you use BackgroundWorker as its shown here http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx with ProgressChanged event it will do the trick.

EDIT: Here is code from that msdn article aplied on your case

//create worker
BackgroundWorker bw = new BackgroundWorker();

//set progress to true
bw.WorkerReportsProgress = true; 

// handle events
bw.DoWork += new DoWorkEventHandler(DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);

//method for work
private DoWork(object sender, DoWorkEventArgs e)
{

BackgroundWorker worker = sender as BackgroundWorker;
List<Test> tests = ....

for (Test t in tests)
{
    switch(t.Name)
    {
        case "Test1":
            //Do something
            break;
        case "Test2":
            //Do something else 
            break;
        ...
        case "TestSpecial":
            // Here I want to:
            // 1. Tell UI to show an image on the screen
            // 2. Wait for the image to show up
            // 3. Continue with my test
            worker.ReportProgress(1);
            break;
        case "TestN+1":
            //Do something completly different
            break;
    }
}
} 

//method for progress
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    //set your image here
}
Tomas Kosar
  • 394
  • 1
  • 10
  • 23
  • Please avoid answers that are links to other sites; such links change unexpectedly, cannot be used by the SO search, and people reading it cannot tell if it actually answers the questions or is just spam. At the very least, provide a summary of what is at the link. – Dour High Arch Jan 20 '14 at 17:31
  • sorry for that i edited my post. i did not thought about that. I just dont like to copy paste and i think even mention of that event should help. i would rather just comment but i cant because i do not have enough reputation. – Tomas Kosar Jan 20 '14 at 18:21
  • ... +1 that you extend the answer as required by Dour. Nice job. – Radim Köhler Jan 31 '14 at 17:26
  • @TomKos it is possible to gibe a pictue with as parameter `System.Drawing.Image` – LFS96 Mar 04 '14 at 14:31
0

I think that poor old @TomKos was onto the answer... if only he'd have explained himself better.

First, please take a look at my example implementation of the BackgroundWorker class in the Progress Bar update from Background worker stalling post here on StackOverflow.

Now, in the DoWork method, please notice the call to backgroundWorker.ReportProgress(i);. This passes a number back to the UI thread that represents the percentage of the work that is complete.

You could implement something like this and pass a particular value back to the UI when you want to display your image. At some stage in your DoWork method, you could pass the value back like this:

private void DoWork(object sender, DoWorkEventArgs e)
{
    // Do some long running process here
    backgroundWorker.ReportProgress(1); // Send signal to show the image
    // Maybe do some more long running process here
}

You would handle it in the UI something like this:

private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    if (e.ProgressPercentage == 1)
    {
        // Show your image
    }
}
Community
  • 1
  • 1
Sheridan
  • 68,826
  • 24
  • 143
  • 183
0

100% of the time there will be a delay from when you tell the UI to show the image and when the image is on the screen. Gamers spends lots of money on graphics cards for a reason.

Loaded is the last event.
The Loaded event is raised before the final rendering, but after the layout system has calculated all necessary values for rendering.

There is no Rendered event (that I am aware of).

I would try a delay in the Loaded event.
100,000 is not that many.
Even 1/10 of a second delay would only be few hours.

paparazzo
  • 44,497
  • 23
  • 105
  • 176