![]() |
|
|
#1 |
|
Guest
Posts: n/a
|
Update UI from Background thread
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); } } } |
|
|
|
#2 |
|
Guest
Posts: n/a
|
Re: Update UI from Background thread
On Fri, 14 Dec 2007 12:12:17 -0800, RSH <way_beyond_oops@yahoo.com> wrote:
> 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 |
|
|
|
#3 |
|
Guest
Posts: n/a
|
Re: Update UI from Background thread
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.GetIn gredient(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.GetBake dGood(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.T oString()); 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); } } } "Peter Duniho" <NpOeStPeAdM@nnowslpianmk.com> wrote in message news p.t3cdvwg18jd0ej@petes-computer.local...> On Fri, 14 Dec 2007 12:12:17 -0800, RSH <way_beyond_oops@yahoo.com> wrote: > >> 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 |
|
|
|
#4 |
|
Guest
Posts: n/a
|
Re: Update UI from Background thread
On Fri, 14 Dec 2007 12:37:42 -0800, RSH <way_beyond_oops@yahoo.com> wrote:
> 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 |
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|