Archive for ‘.NET’

May 22, 2012

Using Task for responsive UI in WPF

Blocking of the UI thread in a WPF application causes the application to become unresponsive. It is a common problem with several solutions, but usage of Task is in my opinion the most elegant solution because of readability and code brevity.
For this example we have a simple WPF application with a button that starts a long running loop. A busy indicator is displayed while the loop is running.

_busyIndicator.IsBusy = true;

for (var i = 0; i < 100; i++)
{
  System.Threading.Thread.Sleep(50);
}

_busyIndicator.IsBusy = false;

As written, this code will freeze the app for the duration of the loop since it blocks execution of the UI thread. The solution is to run the loop Asynchronously and using Task is the easiest way to accomplish it in this case.

_busyIndicator.IsBusy = true;

var T = new Task(() =>
{
  for (var i = 0; i < 100; i++)
  {
    System.Threading.Thread.Sleep(50);
  }
});

T.Start();

_busyIndicator.IsBusy = false;

However, this bit of code will crash the application because we have not passed control back to the context of the UI thread. The ‘Task.ContinueWith’ method can be used to serve that purpose.

var T = new Task(() =>
{
  for (var i = 0; i < 100; i++)
  {
    System.Threading.Thread.Sleep(50);
  }
});

T.ContinueWith(antecedent => _busyIndicator.IsBusy = false, TaskScheduler.FromCurrentSynchronizationContext());

Running the application will now result in complete responsiveness. You can move, resize, or perform other operations while the loop is running. However, there are cases where CPU intensive loops may cause the busy indicator to not be displayed. In WPF, the UI render events are queued to prevent issues related to multiple execution of the same event. To prevent this, we want to make sure that the busy indicator is displayed. And for that we can use a timer event.

private System.Windows.Threading.DispatcherTimer _timer = null;
public MainWindow()
{
  InitializeComponent();
  _timer = new DispatcherTimer();
  _timer.IsEnabled = false;
  _timer.Tick += new System.EventHandler(RunTask);
}

private void StartProcess(object sender, RoutedEventArgs e)
{
  _busyIndicator.IsBusy = true;
  _timer.Interval = new TimeSpan(0,0,0,0,100);
  _timer.Start();
  // go back to the user thread, giving the busy indicator a chance to come up before the next timer tick event
}

void RunTask(object sender, System.EventArgs e)
{
  _timer.IsEnabled = false;

  var T = new Task(() =>
  {
    for (var i = 0; i < 100; i++)
    {
      System.Threading.Thread.Sleep(50);
    }
  });

  T.ContinueWith(antecedent => _busyIndicator.IsBusy = false, TaskScheduler.FromCurrentSynchronizationContext());
  T.Start();
}

So, when the user clicks the button, the busy indicator is set to true first, the timer is started, and once it has ticked the Task is called. Using the timer event in this manner ensures that the loop will not be executed until the busy indicator is rendered.

The complete source code for this example can be found in our github repository.

Advertisements
Tags: ,
March 13, 2012

Forcing a single instance of a process in .Net with Mutex

In a recent application, a requirement was to allow for only a single instance to be running at a time. Typically I would do this with Systems.Diagnostics.Process and search for an instance of my running application, but I wanted to try the Mutex method because it appeared to be simpler and a bit lighter.

A Mutex is a synchronization primitive that can be used for interprocess synchronization while most other locking mechanisms are process specific. You can read more about Mutex here</>.

It turned out to be much simpler than I had expected, so I thought I would share how to set it up in a Windows Form project. The first step is to add a class with some native methods that are required to bring the application to the top if it is already running.

class NativeMethods
{
    public const int HWND_BROADCAST = 0xffff;
    public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");
    [DllImport("user32")]
    public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
    [DllImport("user32")]
    public static extern int RegisterWindowMessage(string message);
}

The next step is to define the Mutex that will be used to identify the process.

static class Program
{
    private static readonly Mutex mutex = new Mutex(true, "{5D562B9B-8B2B-4A30-979A-083BDE97B99E}");
    ...

The Mutex.WaitOnce method provides the magic for checking if our process is already running. It has an overload that takes two parameters; Time to wait and a Boolean for exiting the context. WaitOnce returns true if it is able to enter and false if it is not. So, with the following, we can launch the application if it is not already open.

if (mutex.WaitOne(TimeSpan.Zero, true))
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());</p>
}

And in the else block the existing process can be brought to the top of the display.

if (mutex.WaitOne(TimeSpan.Zero, true))
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
    mutex.ReleaseMutex();</p>
}
else
{
    NativeMethods.PostMessage(
    (IntPtr)NativeMethods.HWND_BROADCAST,
    NativeMethods.WM_SHOWME,
    IntPtr.Zero,
    IntPtr.Zero);</p>
}

So there you have it. The application will only allow for one instance and will be brought to the front of the display if a user attempts to launch it while it is running.

January 12, 2012

Large WCF Requests, Don’t forget httpRuntime settings

Recently, I was working on a project where the client was passing an array of bytes (byte[]) into a WCF service method. The array represented a file the user wanted to upload to the server. The WCF service was throwing cryptic error messages when the user attempted to upload a large file. There are obvious issues with this approach, but without a redesign of the upload process, my client was looking for a quick fix. There are many articles that cover the various options that one has to adjust under serviceBehaviors for WCF (e.g. maxReceivedMessageSize), but increasing all of those to their maximum value DID NOT solve the problem.

After looking at the issue through a packet filter, I finally figured out that IIS was rejecting the request at a level above WCF and then I remember the httpRuntime config section. You can read about it here:
http://msdn.microsoft.com/en-us/library/e1f13641

The relevant attribute is maxRequestLength

The default is 4096KB as of the writing of this post.

Obviously, no matter what other settings you tweak, if you run into this limit, IIS will block the request.

This can also come up when writing plain old vanilla ASP.NET file upload if you’re not streaming the file to the server.

Streaming files to your server would avoid running into these problems, but if you’re in a pinch and working on an internal application used by a small number of users, this is the quick and dirty way to get around the limit.

Tags: ,