Posts tagged ‘.net’

January 11, 2012

Homegrown Dynamic IP Tracking

I often need to remotely access my home computer. Since dynamic DNS services are not always available to me, I needed a way to be notified when my ISP issued a new IP address. The first task was to choose one of the many services that happily provide your public address. The ideal candidate would be one that gives a relatively easy to parse response. After a bit of searching, I found that the nice folks over at http://dyndns.org offer just that with http://checkip.dyndns.org

The .Net WebClient provides an easy means to retrieve the response:

var client = new WebClient();
var response = client.DownloadString("http://checkip.dyndns.org");

After a bit of simple parsing, we have our public IP address:

const string startToken = "Current IP Address: ";
var startIndex = response.IndexOf(startToken);
startIndex += startToken.Length;
var endIndex = response.IndexOf("</body>");
var ip = response.Substring(startIndex, endIndex - startIndex);

Now that we have the public IP address, notification becomes a task for the .Net SmtpClient. Using email as the notification method certainly isn’t the only solution, but has the benefit of being private. For this particular project, I’m using an App.config to populate properties of the SmtpClient.

var appSettings = ConfigurationManager.AppSettings;
var email = Convert.ToString(appSettings["EmailAddress"]);
var displayName = Convert.ToString(appSettings["DisplayName"]);
var fromAddress = new MailAddress(email, displayName);
var toAddress = new MailAddress(email, displayName);
var fromPassword = Convert.ToString(appSettings["EmailPassword"]);
var smtp = new SmtpClient
            {
                Host = Convert.ToString(appSettings["EmailHost"]),
                Port = Convert.ToInt32(appSettings["EmailPort"]),
                EnableSsl = Convert.ToBoolean(appSettings["EnableSsl"]),
                DeliveryMethod = SmtpDeliveryMethod.Network,
                UseDefaultCredentials = false,
                Credentials = new NetworkCredential(fromAddress.Address, fromPassword)</p>
            };

And now, sending the message is simply a matter of constructing a .Net MailMessage and passing it to the SmtpClient Send method.

var subject = "Current Home IP Address: " + ip;
var body = subject;
using (var message = new MailMessage(fromAddress, toAddress)
{
    Subject = subject,
    Body = body
})
{
    smtp.Send(message);
}

It is certainly feasible to schedule a daily task for this to run, but I decided to wrap it into a service so notification emails are only sent if the public IP changes. The entire project can be found in our brand new github repository linked below.

https://github.com/yojimbocorp/blog-posts

Advertisements
December 27, 2011

How to Show the Silverlight Busy Indicator When Your Task Has to Run on the UI Thread

Warning: this is a “hack” to be used when all other options have been exhausted

Recently, I was working on a project that required me to implement export to Excel from a third-party grid. The task was quite simple as the grid control already had a method for the purpose of creating a workbook. However, when using the method from a button click handler my entire UI would freeze for the duration of the export. The export had to be performed on the UI thread, because it relied on a method located on the control (which in turn touched other properties of the control). I knew I couldn’t get around the freeze, but wanted to display a busy indicator. After searching the web I failed to find a solution. The issue is that the busy indicator itself has to use the UI thread to begin animating and Silverlight queues user interface updates (to improve performance), so just because you set the ‘IsBusy’ property true, you’re not guaranteed that the user has seen the indicator.

I had some work to do before kicking off the export and was already spawning a background thread via the method ThreadPool.QueueUserWorkItem.

However, the only way to get the busy indicator to display was to add a Sleep operation as the first step of my thread and I wasn’t sure how long I needed to sleep before I had some indication that the busy indicator has displayed.

My final workaround consisted of the following steps:

1)      Implement the LayoutUpdated event on the BusyIndicator instance. Inside this event, I set a private bool field to true. The field is marked as volatile to prevent compiler optimizations which sometimes cause multiple threads to see a different value (the alternative would have been to use another field and lock on it when touching the bool).

2)      In my button click event, I set the private field to false anytime I set the ‘IsBusy’ property of the busy indicator to true.

3)      I then added this code block at the top of my background task (basically waiting for the busy indicator to update its layout – i.e. display itself) before doing any other work:

while (!_hasBusyIndicatorUpdatedLayout)
{
         Thread.Sleep(100);
}

After exiting this while loop, I kicked off the call to process my Excel export on the UI thread.

There are a couple of issues with this solution:

1)      It’s a hack

2)      The busy indicator’s animation will be frozen (along with the entire application)

However, the alternative was to have a frozen UI all around. I am attaching a sample project implementing all of the above. If you want to see what happens without the check, just comment out the ‘while’ loop shown above.

If anyone has come up with a more elegant solution or improves upon this, please comment below.

The complate click handler looks like this:

private void ButtonClick(object sender, RoutedEventArgs e)
{
    SetBusy("Exporting data...");

    ThreadPool.QueueUserWorkItem((state) => 
    {
        // this is how we check if the busy indicator has 
        // started to display to the user
        while (!_hasBusyIndicatorUpdatedLayout)
        {
            Thread.Sleep(100);
        }

        // now we can perform our busy task
        DoBusyWorkOnUiThread();
        RemoveBusy();
    });
}

Download the project below for the full implementation. If you comment out the line in the constructor that does this:

busyIndicator.LayoutUpdated += BusyIndicatorLayoutUpdated;

You will see that the busy indicator no longer displays.

Download Project

Tags: , ,