Update UI from Background thread

R

RSH

Hi,

I have an Asynchronus process that is reporting back to the UI at regular
intervals. I read several posts on how to use delegates to make this
happen. But for some reason my application just hangs, nothing being
written it just hangs. when I comment out the "Invoke(new
UpdateTextCallback(UpdateText));" it works fine.

What am I missing?

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void button1_Click(object sender, EventArgs e)

{

EventMonitor.ProcessMonitor += new ProcessMonitorHandler(DisplayEvents);

Party m_Party = new Party();

}

private void DisplayEvents(object sender, ProcessEventArgs e)

{

if (InvokeRequired)

{

System.Diagnostics.Debug.WriteLine("HIT!");

Invoke(new UpdateTextCallback(UpdateText));

}

else

{

richTextBox1.Text += e.EventArg + "\r\n";

}

Application.DoEvents();

}

private void UpdateText(object sender, ProcessEventArgs e)

{

System.Diagnostics.Debug.WriteLine("HIT!");

richTextBox1.Text += e.EventArg + "\r\n";

}

public delegate void UpdateTextCallback(object sender, ProcessEventArgs e);

public delegate void ProcessMonitorHandler(object sender, ProcessEventArgs
e);

}







public static class EventMonitor

{

public static event ProcessMonitorHandler ProcessMonitor;

public static void BroadcastEvent(string Event)

{

OnEvent(Event);

}

static void OnEvent(string Event)

{

if (ProcessMonitor != null)

{

ProcessEventArgs e = new ProcessEventArgs();

e.EventArg = Event;

ProcessMonitor(null, e);

}

}

}
 
P

Peter Duniho

I have an Asynchronus process that is reporting back to the UI at regular
intervals. I read several posts on how to use delegates to make this
happen. But for some reason my application just hangs, nothing being
written it just hangs. when I comment out the "Invoke(new
UpdateTextCallback(UpdateText));" it works fine.

Well, you didn't post a complete code sample. So no one can say for sure
what's going on.

But my suspicion is that even though you're using (you say) a separate
thread for the async processing, your Click event handler doesn't return
right away but instead waits for the processing to complete. With the
main GUI thread blocked, there's no way for the call to Invoke() to
complete, and thus you get a deadlock.

If you want a better answer, you need to post a concise-but-complete
sample of code that reliably demonstrates the problem.

Pete
 
R

RSH

Okay sorry...





Form Code:
namespace TestObjectInteraction

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void button1_Click(object sender, EventArgs e)

{

EventMonitor.ProcessMonitor += new ProcessMonitorHandler(DisplayEvents);

Party m_Party = new Party();

}

private void DisplayEvents(object sender, ProcessEventArgs e)

{

System.Diagnostics.Debug.WriteLine(e.EventArg);

if (this.richTextBox1.InvokeRequired)

{

this.richTextBox1.Invoke(new ProcessMonitorHandler(DisplayEvents), sender,
e);

}

else

{

richTextBox1.Text += e.EventArg + "\r\n";

}

Application.DoEvents();

}

}

}



//Event Monitor Class

public static class EventMonitor

{

public static event ProcessMonitorHandler ProcessMonitor;

public static void BroadcastEvent(string Event)

{

OnEvent(Event);

}

static void OnEvent(string Event)

{

if (ProcessMonitor != null)

{

ProcessEventArgs e = new ProcessEventArgs();

e.EventArg = Event;

ProcessMonitor(null, e);

}

}

}





// Baker Class

public class Baker

{

private CookBook m_CookBook = new CookBook();

private Oven m_Oven = new Oven();

private Recipe m_Recipe;

private MixingBowl m_MixingBowl = new MixingBowl();

private IBakingPlatform m_BakingPlatform;

private BakedGoods m_BakedGoods;

private bool bDoneMixing;

private bool bOvenPreheated;

public event BakedGoodServingHandler Served;

public void BakeCookies()

{

EventMonitor.BroadcastEvent("Baker is looking up recipe...");

m_Oven.DoneCooking += new FinishedCookingHandler(OnDoneCooking);

m_Oven.TempChange += new TempChangeHandler(m_Oven_TempChange);

m_Recipe = m_CookBook.GetCookieRecipe();

m_BakingPlatform =
BakingPlatformFactory.GetBakingPlatform(eBakeType.Cookie);

PreheatOven();

foreach (KeyValuePair<eRecipeItems, int> item in m_Recipe.RecipeCollection)

{

for (int i = 0; i <= item.Value; i++)

{

EventMonitor.BroadcastEvent(string.Format("Baker is adding ingredient
{0}...", item.Key.ToString()));

m_MixingBowl.AddIngredient(IngredientFactory.GetIngredient(item.Key));

}

}

MixIngredients();

}

private void m_Oven_TempChange(object sender, int temp)

{

EventMonitor.BroadcastEvent(string.Format("Oven is reporting a temperature
of {0} degrees...", temp));

}

private delegate void MixIngredientsDelegate();

private delegate void PreheatOvenDelegate();

private void MixIngredients()

{

EventMonitor.BroadcastEvent("Baker is mixing ingredients...");

MixIngredientsDelegate sampleDelegate = new
MixIngredientsDelegate(MixIngredientsHandler);

IAsyncResult aResult = sampleDelegate.BeginInvoke(null, null);

aResult.AsyncWaitHandle.WaitOne();

sampleDelegate.EndInvoke(aResult);

bDoneMixing = true;

if (bOvenPreheated == true)

{

PutBakingPlatformInOven();

}

}

private void MixIngredientsHandler()

{

m_MixingBowl.MixIngredients();

}

private void PreheatOven()

{

EventMonitor.BroadcastEvent("Baker is preheating the oven...");

MixIngredientsDelegate sampleDelegate = new
MixIngredientsDelegate(PreheatOvenHandler);

IAsyncResult aResult = sampleDelegate.BeginInvoke(null, null);

aResult.AsyncWaitHandle.WaitOne();

sampleDelegate.EndInvoke(aResult);

bOvenPreheated = true;

EventMonitor.BroadcastEvent("Baker has been alerted that the oven is
preheated...");

if (bDoneMixing == true)

{

PutBakingPlatformInOven();

}

}

private void PreheatOvenHandler()

{

m_Oven.Preheat(m_Recipe.CookTemperature);

}

private void PutBakingPlatformInOven()

{

m_Oven.Bake(m_Recipe.CookTime);

}

private void OnDoneCooking(object sender, EventArgs e)

{

EventMonitor.BroadcastEvent("Baker is removing Baked Goods from Oven...");

m_BakedGoods = new BakedGoods(m_Recipe.BakeType);

EventMonitor.BroadcastEvent("Baker is placing baked goods onto the serving
tray...");

for (int i = 0; i <= m_Recipe.Yields; i++)

{

m_BakedGoods.AddBakedGood(BakedGoodFactory.GetBakedGood(m_Recipe.BakeType));

}

ServeBakedGoods();

}

protected virtual void ServeBakedGoods()

{

if (Served != null)

{

BakedGoodEventArgs eventargs = new BakedGoodEventArgs();

eventargs.Count = m_Recipe.Yields;

eventargs.Type = m_Recipe.BakeType;

Served(null, eventargs);

}

}

public void BakeCake()

{

}

}





//Oven class

public class Oven

{

private int m_BakingTemp = 0;

private int m_CurrentTemp = 0;

public event TempChangeHandler TempChange;

public event PreheatedHandler Preheated;

public event FinishedCookingHandler DoneCooking;

public void Preheat(int temperature)

{

int j = 0;

m_BakingTemp = temperature;

for (int i = 0; i < m_BakingTemp; i++)

{

//System.Threading.Thread.Sleep(100);

m_CurrentTemp = i;

if (j == 10)

{

//System.Diagnostics.Debug.WriteLine(m_CurrentTemp.ToString());

OnTempChange();

j = 0;

}

j++;

}

OnPreHeated();

}

protected virtual void OnPreHeated()

{

if (Preheated != null)

{

Preheated(null, m_CurrentTemp);

}

}

protected virtual void OnTempChange()

{

if (TempChange != null)

{

TempChange(null, m_CurrentTemp);

}

}

public void Bake(int CookTime)

{

for (int i = 0; i <= CookTime; i++)

{

System.Threading.Thread.Sleep(500);

}

OnDoneCooking();

}

protected virtual void OnDoneCooking()

{

if (DoneCooking != null)

{

DoneCooking(null, null);

}

}

}
 
P

Peter Duniho

Okay sorry...

The code you posted is not a concise sample. "Concise" means that there
is nothing in the code that is not directly related to reproducing the
problem.

If you're having trouble understanding what is needed in your sample, you
might find Jon Skeet's article useful:
http://www.pobox.com/~skeet/csharp/complete.html While are some details
in there that I feel differently about, on the whole he describes exactly
what I mean when I write "concise-but-complete".

Also, for some reason the code is winding up posted without any
indentation. Providing a concise sample is mandatory, but it would be
nice if you could also figure out the indentation issue. It's really hard
to read the code otherwise.

Pete
 
C

christery

And maybe more about what the problem is, not getting UI, not getting
it compiled, not getting EventMonitor.BroadcastEvent working...

Yes it is easyer to read indented code without blank rows... seen the
same problem with cut/paste in the wrong format, might try going over
notepad as in cup and paste to notepad and from there to web... all
swedish char WILL annoyngy be disorted but thats wont a problem in
this case ;)

Im grumpy, I know.. just woked up and realizing its almost monday...
again...

//CY
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top