[Mono-dev] GTK# Window Display Issue Outside of Main.cs

Ivo Smits Ivo at UFO-Net.nl
Tue Nov 6 22:49:14 UTC 2012


Hello Johnnie,

Is the worker function (in the worker class) running on a separate 
thread? Is it started using a Thread/ThreadPool/BeginInvoke? This is 
probably the case, but it's not clear from the code you've provided. Can 
you show the code that calls radiazerMain? Main.cs?

Normally, only one thread in your application runs the GUI event loop 
(Application.Run() for WinForms, GTK# must have something similar). Only 
this thread can create and change windows (including all 
controls/widgets on those windows).

The usual way to work around this restriction is by using the 
Invoke/BeginInvoke calls (in WinForms) on a window/form/control, or in 
some other way "post" a request to call a function on the GUI thread. 
The specified callback function is then called on the right thread and 
can update the GUI.

Another option is to expose the worker progress as a public property, 
and create a Timer (again WinForms, GTK probably has something similar) 
to periodically read this property and update the GUI.

Another thing you can't/shouldn't do: run the worker function on the GUI 
thread (for example through a direct call from a Window load function or 
button click handler). This will block the GUI thread - and all event 
processing including updates - until the worker has finished, resulting 
in the well known "Application is not responding" error on Windows.

I hope this helps.

Ivo

Op 6-11-2012 22:55, Johnnie Odom schreef:
>
> Hello Everyone,
>
>
> This is my first day on the mailing list, and as it is I have a 
> question regarding some odd behavior I am encountering. I have also 
> posted this message to the GTK# list as I am not sure which is the 
> more appropriate venue.
>
>
> I am writing an application on OS X 10.8 using C#, Mono 2.10.9 and 
> MonoDevelop 3.0.4 (including the Designer views) that makes some 
> simple changes to LDAP. As part of it, I decided to get fancy with 
> GTK#. All is going well, except for one behavior.
>
>
> I have created a window class to display a progress bar and stop 
> button. I have further created a function in this class to update the 
> progress bar with a fraction and text message. In my code, I create a 
> new instance of this window class when real work is happening in 
> another class, and then populate it after every ten iterations of a 
> foreach loop.
>
>
> My problem is that when the window is created FROM THE CLASS DOING 
> REAL WORK, it displays neither the progress bar widget, nor the 
> button. It displays only the window title and then white space below. 
> Only this window displays this behavior -- several other windows that 
> I create over the course of the application all display appropriately.
>
>
> If I instead create the progress bar window in Main.cs and call 
> Show(), it will display just fine. I can even call the function to set 
> its status from Main.cs and it will display correctly.
>
>
> I have tried creating the window in Main.cs and passing it to the 
> class that does the real work later. I have tried creating it in other 
> classes besides the one that does the work. In all cases the behavior 
> is the same -- if the window is created and used solely in Main.cs it 
> will display fine, but if it it ever invoked or created from anywhere 
> else (whether or not it is created in another class or in Main.cs) it 
> will display incorrectly.
>
>
> I have taken to using the debugger and break points to isolate the 
> behavior. If I set a breakpoint immediately after the window is 
> created, it is still blank -- that is, I do not think it is a case 
> that the window is just not keeping pace with any updates I am 
> sending. I have also compared the various values of the window objects 
> and attributes when it is displayed (created and used solely in 
> Main.cs) and when it is not (displayed in any other class) and they 
> seem to be identical.
>
>
> So, I am at a loss, and I would appreciate any advice you might give.
>
>
> I can send any code you think would prove useful, but for now I am 
> sending you the class where I am trying to call the window, and the 
> contents of the window's code-behind.
>
>
> Thank you for any guidance you can give.
>
>
> Johnnie Odom
>
> Network Services
>
> School District of Escambia County
>
>
> ****************
>
>
> The function from the calling class:
>
> public string radiazerMain(string radiazerGroup, string radiazerProfile){
>
> Progression MarathonBar = new Progression();
>
> MarathonBar.Show();
>
> string monologger = "";
>
> string lastLine = "Radiazer completed current run." + 
> Environment.NewLine;
>
> Array usersToModify = getGroupMembers(radiazerGroup);
>
> string[] radiusAttribs = new 
> string[]{"dialupAccess","radiusArapFeatures","radiusArapSecurity","radiusArapZoneAccess","radiusAuthType","radiusCallbackId","radiusCallbackNumber","radiusCalledStationId","radiusCallingStationId","radiusCheckItem","radiusClass","radiusClientIPAddress","radiusExpiration","radiusFilterId","radiusFramedAppleTalkLink","radiusFramedAppleTalkNetwork","radiusFramedAppleTalkZone","radiusFramedCompression","radiusFramedIPAddress","radiusFramedIPNetmask","radiusFramedIPXNetwork","radiusFramedMTU","radiusFramedProtocol","radiusFramedRoute","radiusFramedRouting","radiusGroupName","radiusHint","radiusHuntgroupName","radiusIdleTimeout","radiusLoginIPHost","radiusLoginLATGroup","radiusLoginLATNode","radiusLoginLATPort","radiusLoginLATService","radiusLoginService","radiusLoginTCPPort","radiusLoginTime","radiusPasswordRetry","radiusPortLimit","radiusProfileDn","radiusPrompt","radiusProxyToRealm","radiusRealm","radiusReplicateToRealm","radiusReplyItem","radiusServiceType","radiusSessionTimeout","radiusSimultaneousUse","radiusStripUserName","radiusTerminationAction","radiusTunnelAssignmentId","radiusTunnelClientEndpoint","radiusTunnelMediumType","radiusTunnelPassword","radiusTunnelPreference","radiusTunnelPrivateGroupId","radiusTunnelServerEndpoint","radiusTunnelType","radiusUserCategory","radiusVSA"}; 
>
>
> LdapAttributeSet profileTemplate = 
> LdapAttributeSetFiltered(radiazerProfile, radiusAttribs);
>
> profileTemplate.Add(new LdapAttribute("radiusProfileDn", 
> radiazerProfile));
>
>
> int totalUsersCount = usersToModify.Length;
>
> int currentUserCount = 0;
>
> int errorCount = 0;
>
> MarathonBar.Show();
>
>
> foreach(string userToModify in usersToModify){
>
> currentUserCount++;
>
> try{
>
> monologger = monologger + radiazeModifyUser(userToModify, 
> profileTemplate);
>
> }
>
> catch(LdapException LdapFailure){
>
> monologger = monologger + "User " + userToModify + " failed. Error is 
> " + LdapFailure.ToString() + Environment.NewLine;
>
> errorCount++;
>
> }
>
> if(((currentUserCount % 10) == 0) || ((totalUsersCount - 
> currentUserCount) < 10)){
>
> MarathonBar.setProgress(((double)currentUserCount / totalUsersCount), 
> totalUsersCount , currentUserCount, errorCount, userToModify);
>
> }
>
> if(MarathonBar.cancelFromUser){
>
> lastLine = "Radiazer cancelled by user." + Environment.NewLine;
>
> break;
>
> }
>
> }
>
>
> MarathonBar.Destroy();
>
> monologger = monologger + lastLine;
>
> return monologger;
>
> }
>
>
> *************
>
>
> The Code-Behind:
>
>
> using System;
>
>
> namespace Radiazer2
>
> {
>
> public partial class Progression : Gtk.Window
>
> {
>
>
> public bool cancelFromUser = false;
>
>
> public Progression () :
>
> base(Gtk.WindowType.Toplevel)
>
> {
>
> this.Build ();
>
> }
>
>
> public void setProgress(double fractionOfProgress, int totalUnits, int 
> finishedUnits, int errorUnits, string finishedUser){
>
> this.progressIndicator.Fraction = fractionOfProgress;
>
> this.progressIndicator.Text = "Completed " + finishedUnits + " of " + 
> totalUnits + " with " + errorUnits + " errors. Current user is " + 
> finishedUser + ".";
>
> }
>
>
> protected void OnStopUserClicked (object sender, EventArgs e)
>
> {
>
> cancelFromUser = true;
>
> }
>
>
>
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ximian.com/pipermail/mono-devel-list/attachments/20121106/65bf7d51/attachment.html>


More information about the Mono-devel-list mailing list