Friday, April 3, 2009

What to do if your C# app shows messages "not responding" at the top of the window.

Sometimes you might see messages "not responding" at the top of the window when you are developing a C# Windows form application.

It if comes back soon,you can leave it as it is.But in case it doesn't,you must do something.So in this post,I will explain why this phenomenon happens and how to prevent it.

The cause of the phenomenon "not responding"
To avoid the phenomenon,the first thing you should do is to know how a Windows application respond to user operations.

When something happens on computer,for example a Button on your application is clicked,Windows Operation System send a information about the incident to the related application.The information is called "message" and the something having happened called "Event".

Every application on Windows function by handling those messages.

To tell this mechanism in more detail,Each application has its own "message queue" and Windows feed a message into the queue every time an event occurs.Every application must have a thread which checks if messages have been sent in the message queue at regular intervals and if they have,handle those messages one by one. Processed Messages are removed from message queue.This whole process that a thread is doing is called "Message loop".

In C# Windows Application,Message loop starts when Application.Run() is called,which is usually written in the auto generated code "Program.cs".

As long as "Message loop" keeps working within a given length of time,application continue responding without showing messages "not responding".

But if a time-consuming message comes into message queue,for example it requires to execute complicate queries,in the meantime the other messages stuck in the message queue.When your code go into this situation,your application will show messages "not responding".Sometimes it happens that "not responding" is followed by the window white out.This is because a message telling your application to draw itself is kept waiting in the queue.

What to do prevent the phenomenon
Now that we know the mechanism,we are very close to our goal.Actually we have several ways to solve the problem.

The easiest way is to call Application.DoEvents() somewhere in the handler code,in case that it has already taken a long time by then.By calling the method the execution goes into handling the other messages first.Then when it finishes,it will return to the beginning of the next line.


private void _searchBtn_Click(object sender, EventArgs e)
{
ExecuteQuery(); //Suppose this takes lots of time
Application.DoEvents();
ExecuteUpdate();
}
But if there is another time-consuming one in the other messages or a single atomic line takes a long time,this manner doesn't work.

Given this factor,We move into thread.Instead of having message loop thread do everything,it can start another thread which actually do the job.This let the main thread return quickly and take care of the others.

To do this,We have three options.the code below is directly starts a thread.



private void _searchBtn_Click(object sender, EventArgs e)
{
try
{
Thread thread = new Thread(new ThreadStart(Execute));
thread.Start();
}
catch {}
}

private void Execute()
{
//Write here what you want to do asyncrously.
}
If you need a foreground thread,this is the only your option,but be aware of overhead of thread creation and disposing.

The code below is the second option.ThreadPool frees your code from the overhead.
Thread pool threads are background threads.If you need a foreground thread,you must go with the first one.


private void _searchBtn_Click(object sender, EventArgs e)
{
try
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Execute));
}
catch {}
}

private void Execute()
{
//Write here what you want to do asyncrously.
}

QueueUserWorkItem() queue a method for execution,in most of the case execution of the method will begin in a moment.

The third option is callBack delegate.Only diffrence from the second one is forms of codes.
CallBack delegate uses ThredPool internally.



private delegate void ExecuteSearchDelegate();

private void _searchBtn_Click(object sender, EventArgs e)
{
try
{
ExecuteSearchDelegate dlgt = new ExecuteSearchDelegate(Execute);
dlgt.BeginInvoke(new AsyncCallback(ExecuteCallback), dlgt);
}
catch {}
}

private void Execute()
{
//Write here what you want to do asyncrously.
}

private void ExecuteCallback(IAsyncResult ar)
{
//Write here what you want to do after the delegate has completed.
}
Be careful,you can't access the controls in the code block executed by a thread that is not message loop.
In the case,you should do like below.



private void _searchBtn_Click(object sender, EventArgs e)
{
try
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Execute));
}
catch {}
}

private void Execute()
{
//Write here what you want to do asyncrously.

Invoke((MethodInvoker)delegate()
{
//Accessing controls.
});
}

Tuesday, March 31, 2009

ActualWidth,ActualHeight returning ZERO

In the development of Silverlight it happens often that you don't assign any value to Width and Height of UI Elements in your code,then in run time those values will be referenced.

In that case ActualWidth and ActualHeight must be something you refer to.But if you write code like below,an unpredictable incident may happen to you.


public Page()
{
InitializeComponent();

//Set the location of the button around the corner of the canvas.
Canvas.SetTop(imageButton, 5);
Canvas.SetLeft(imageButton, LayoutRoot.ActualWidth - 25);
}
In the code above ActualWidth of the root canvas is referenced to put the button near the corner of the canvas.But the code fails to get the anticipated value.Actually it returns zero value.So I moved the lines to Loaded event handler,but it didn't make any difference.

At first, I was quite at a loss what should I do.But I went back to basics and referenced documents again,I found the solution.

Value of ActualWidth and ActualHeight are given after layout calculation process has completed.And the process is executed asyncronously ,which means the calculation process is registered in queue of the related thread at the moment when changes have been made to the UI elements.

Then after all lines in a current block executed,the calculation process will begin.

So What to do is to put "referencing ActualWidth and ActualHeight" also in the same queue,which means you should write code like this.


public Page()
{
InitializeComponent();

Dispatcher.BeginInvoke(
() =>
{
Canvas.SetTop(imageButton, 5);
Canvas.SetLeft(imageButton, LayoutRoot.ActualWidth - 25);
}
);


}
BeginInvoke method in Dispatcher in Silverlight API doesn't have paremeter to designate priority.So I think the order you add delgates determines the order of execution, which turns out "Referencing ActualWidth" always comes after layout calculation process in the code above.

I just wanted to make sure my assumption about order of execution,I wrote and run the code below several times.


Dispatcher.BeginInvoke(
() =>
{
Debug.WriteLine("1");
}
);

Dispatcher.BeginInvoke(
() =>
{
Debug.WriteLine("2");
}
);

Dispatcher.BeginInvoke(
() =>
{
Debug.WriteLine("3");
}
);
Numbers were displayed in order "123" all the time,that was what I had anticipated.

I am not a native english speaker,so if my explanation is not good enough for you to understand, Plaese let me know ,I will be grateful.

Privacy Policy

If you require any more information or have any questions about our privacy policy, please feel free to contact us by email at mykonos2008@hotmail.co.jp.


At eklabjapan.blogspot.com/, the privacy of our visitors is of extreme importance to us. This privacy policy document outlines the types of personal information is received and collected by eklabjapan.blogspot.com/ and how it is used.

Log Files
Like many other Web sites, eklabjapan.blogspot.com/ makes use of log files. The information inside the log files includes internet protocol ( IP ) addresses, type of browser, Internet Service Provider ( ISP ), date/time stamp, referring/exit pages, and number of clicks to analyze trends, administer the site, track user’s movement around the site, and gather demographic information. IP addresses, and other such information are not linked to any information that is personally identifiable.


Cookies and Web Beacons
eklabjapan.blogspot.com/ does use cookies to store information about visitors preferences, record user-specific information on which pages the user access or visit, customize Web page content based on visitors browser type or other information that the visitor sends via their browser.


DoubleClick DART Cookie


.:: Google, as a third party vendor, uses cookies to serve ads on your site.

.:: Google's use of the DART cookie enables it to serve ads to your users based on their visit to your sites and other sites on the Internet.

.:: Users may opt out of the use of the DART cookie by visiting the Google ad and content network privacy policy at the following URL - http://www.google.com/privacy_ads.html


Some of our advertising partners may use cookies and web beacons on our site. Our advertising partners include .......
Google Adsense


These third-party ad servers or ad networks use technology to the advertisements and links that appear on eklabjapan.blogspot.com/ send directly to your browsers. They automatically receive your IP address when this occurs. Other technologies ( such as cookies, JavaScript, or Web Beacons ) may also be used by the third-party ad networks to measure the effectiveness of their advertisements and / or to personalize the advertising content that you see.


eklabjapan.blogspot.com/ has no access to or control over these cookies that are used by third-party advertisers.


You should consult the respective privacy policies of these third-party ad servers for more detailed information on their practices as well as for instructions about how to opt-out of certain practices. eklabjapan.blogspot.com/'s privacy policy does not apply to, and we cannot control the activities of, such other advertisers or web sites.


If you wish to disable cookies, you may do so through your individual browser options. More detailed information about cookie management with specific web browsers can be found at the browsers' respective websites.

Monday, March 30, 2009

Making a Silverlight app getting data from Google app Engine


Recently I am interested in Silverlight2 and Google App Engine.
So I've made a simple Silvelight2 app getting data from a mod on Google App Engine.

I adopted REST Protocol in communication between Silverlight2 and App Engine.

Here is the Server-Side code written in Python,about which you don't have any other choice.


#!-*- coding:utf-8 -*-
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

class MainPage(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/xml'
self.response.out.write('<?xml version="1.0" encoding="UTF-8" ?>')
self.response.out.write('<Person>')
self.response.out.write('<LastName>Jackson</LastName>')
self.response.out.write('<FirstName>Michael</FirstName>')
self.response.out.write('</Person>')

application = webapp.WSGIApplication(
[('/', MainPage)],
debug=True)

def main():
run_wsgi_app(application)

if __name__ == "__main__":
main()

The code above simply returns XML format string.

XML Format:


<?xml version="1.0" encoding="UTF-8" ?>
<Person>
<LastName>Jackson</LastName>
<FirstName>Michael</FirstName>
</Person>
Next is the Client-Side code.

Silverlight2 has XML Serialize API. With it you can Deserialize XML String to a C# Class insntance.

So I defined Person class in first that corresponds to the XML format.

Person.cs:

public class Person
{
public String LastName { get; set; }
public String FirstName { get; set; }
}
The following code makes an Asynchronous http request.
WebRequest class in Silverlight doesn't have GetResponse() which is synchronous version of BeginGetResponse() existing in .NET Framework.


private String _svrUrl = "http://localhost:8080/";

private void OnLoaded(Object sender, RoutedEventArgs e)
{
try
{
WebRequest req = WebRequest.Create(new Uri(_svrUrl));
req.Method = "GET";

req.BeginGetResponse(new AsyncCallback(GetResponseCallback), req);
}
catch { }
}
The callback method is called when the server return a response,
then I start reading data from the response stream asynchronously using ThreadPool class.


private void GetResponseCallback(IAsyncResult ar)
{
try
{
WebRequest req = ar.AsyncState as WebRequest;
WebResponse res = req.EndGetResponse(ar);

Stream stream = res.GetResponseStream();

ThreadPool.QueueUserWorkItem(new WaitCallback(ReadContents), stream);
}
catch { }
}
In the last part,we deserialize the person class instance from the XML Stirng read from stream.

Be sure to use Dispather accessing to a control in a code block executed by a diffrent thread.


private void ReadContents(Object stream)
{
Person person = null;

using (StreamReader reader = new StreamReader(stream as Stream))
{
XmlSerializer serializer = new XmlSerializer(typeof(Person));

person = serializer.Deserialize(reader) as Person;

}

Dispatcher.BeginInvoke(
() => {
_lastName.Text = person.LastName;
_firstName.Text = person.FirstName;
}
);
}