tsJensen

A quest for software excellence...

Convert Pressure to Deliver into Positive Energy and Thinking

Lately I've become alarmed at the negative level of my thinking at times with respect to my work which can then spill over into my personal life. I've been wondering how I can more consistently harness all the latent energy in the pressure to deliver within the constraints of limited resources, tight deadlines and even tighter budgets and convert that to more positive thinking.

I know the value of positive thinking and the resultant self-reinforcing confidence. It leads to greater achievement, productivity and happiness. And yet negative thinking can so easily overwhelm us when the deck seems stacked against us.

I was pondering this question when I remembered a post from Seth Godin called The Problem with Positive Thinking. Here's part of it:

“All the evidence I've seen shows that positive thinking and confidence improves performance. In anything. ... Key question then: why do smart people engage in negative thinking? Are they actually stupid? ... Negative thinking protects us and lowers expectations. ... If positive thinking was easy, we'd do it all the time. Compounding this difficulty is our belief that the easy thing (negative thinking) is actually appropriate, it actually works for us. The data is irrelevant. We're the exception, so we say. Positive thinking is hard. Worth it, though.“ (Seth Godin, September 2009)

Tomorrow, I will actively think more positively. I will lay aside negative thoughts and entertain only the positive. I will convert and harness the energy of the pressure to deliver and channel that energy into positive, productive valuable thinking. Wish me luck!

Generic Asynchronous Wrapper for .NET

Recently I extended a previous blog post and published it on Code Project under the title Generic WCF Service Host and Client. An astute reader asked about calling a service method asynchronously, something I had not given much thought.

I decided that I wanted a way to support asynchronous calls on the generic WCF client without having to modify my service contract (interface) or implementation class libraries. I also wanted a way to do asynchronous calls with as little client code as possible, which meant support for a simple event based solution.

So I went to work experimenting. If you want the WCF version of the solution, visit the Code Project article and you can get the updated code there just as soon as I get an update published.

In this post, I'll present a more generalized version of the solution I created. The GenericAsyncWrapper<T> class is the heart of the solution. Take any instance of T (any class) and GenericAsyncWrapper<T> puts an event based asynchronous wrapper that allows you to call any method on the instance asynchronously.

I'm not going to explain how standard delegates are used to make asynchronous calls. If you want to brush up on the basics, check out Microsoft's How to call a Visual C# method asynchronously along with thousands of other online resources. I will show some examples of using standard generic delegates to do the asynchronous calls to compare with the use of the generic wrapper's event model.

Here's my test class. It does nothing, as you can see, but it does allow me to test my wrapper.

internal class MyTestClass
{
  public void DoNothingNoParams()
  {
    Console.WriteLine("MyTestClass.DoNothingNoParams called on thread: {0}", 
      Thread.CurrentThread.ManagedThreadId);
  }

  public string DoSomething(string input)
  {
    Console.WriteLine("MyTestClass.DoSomething called on thread: {0}", 
      Thread.CurrentThread.ManagedThreadId);
    return "Output of DoSomething with " + input + " as input.";
  }
}

And here's the test code. Just a simple console app that first shows the test class being called directly, then using standard generic delegates and finally using the wrapper. One advantage you may note is that with the wrapper, you also get all your original input params back.

class Program
{
  static void Main(string[] args)
  {
    Console.WriteLine("Main called on thread: {0}", Thread.CurrentThread.ManagedThreadId);
    Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++");
    Console.WriteLine("synchronous calls");
    var mytest = new MyTestClass();
    mytest.DoNothingNoParams();
    string output = mytest.DoSomething("my name is Tyler");
    Console.WriteLine(output);

    Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++");
    Console.WriteLine("Action<> and Func<> delgate calls");
    Action action = new Action(mytest.DoNothingNoParams);
    action.BeginInvoke(new AsyncCallback(ActionCallback), "test1");

    Func<string, string> func = new Func<string, string>(mytest.DoSomething);
    func.BeginInvoke("my name is Arnold", new AsyncCallback(FuncTTCallback), "test2");

    Thread.Sleep(1000);

    Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++");
    Console.WriteLine("asynchronous wrapper calls");
    var wrapper = new GenericAsyncWrapper<MyTestClass>(mytest);
    wrapper.AsyncCompleted += new EventHandler<GenericAsyncWrapperCompletedEventArgs>(wrapper_AsyncCompleted);
    wrapper.AsyncInvoke("DoSomething", "test2", "my name is Bob");
    wrapper.AsyncInvoke("DoNothingNoParams", "test1", null);

    Console.ReadLine();
  }

  static void FuncTTCallback(IAsyncResult result)
  {
    Console.WriteLine("FuncTTCallback called on thread: {0}", Thread.CurrentThread.ManagedThreadId);
    Thread.Sleep(250);
    Func<object, object> deleg = ((AsyncResult)result).AsyncDelegate as Func<object, object>;
    if (deleg != null)
    {
      object returnValue = deleg.EndInvoke(result);
      Console.WriteLine("FuncTTCallback return value: {0}", returnValue);
    }
  }

  static void ActionCallback(IAsyncResult result)
  {
    Console.WriteLine("ActionCallback called on thread: {0}", Thread.CurrentThread.ManagedThreadId);
    Thread.Sleep(250);
    Action deleg = ((AsyncResult)result).AsyncDelegate as Action;
    if (deleg != null)
    {
      deleg.EndInvoke(result);
    }
  }

  static void wrapper_AsyncCompleted(object sender, GenericAsyncWrapperCompletedEventArgs e)
  {
    Console.WriteLine("wrapper_AsyncCompleted called on thread: {0}", Thread.CurrentThread.ManagedThreadId);
    if (e.Error == null)
    {
      Console.WriteLine("methodName: {0}, userState: {1}, result: {2}", 
        e.MethodName, e.UserState, e.Result);
      if (e.InValues != null)
      {
        for (int i = 0; i < e.InValues.Length; i++)
        {
          Console.WriteLine("   value[{0}] = {1}", i, e.InValues[i]);
        }
      }
    }
    else
    {
      Console.WriteLine(e.Error.ToString());
    }
  }
}

Now here's the real magic. The GenericAsyncWrapper<T> class and its attendant event args class.

public class GenericAsyncWrapper<T> where T : class
{
  private T _instance;

  public GenericAsyncWrapper(T instance)
  {
    if (instance == null) throw new NullReferenceException("instance cannot be null");
    _instance = instance;
  }

  public T Instance { get { return _instance; } }

  public event EventHandler<GenericAsyncWrapperCompletedEventArgs> AsyncCompleted;

  public void AsyncInvoke(string methodName, object userState, params object[] inValues)
  {
    if (string.IsNullOrEmpty(methodName)) throw new NullReferenceException("methodName cannot be null");
    MethodInfo mi = this.Instance.GetType().GetMethod(methodName);
    if (null != mi)
    {
      Func<MethodInfo, object[], object> func = new Func<MethodInfo, object[], object>(this.ExecuteAsyncMethod);
      func.BeginInvoke(mi, inValues, new AsyncCallback(this.FuncCallback), 
        new GenericAsyncState() { UserState = userState, MethodName = methodName, InValues = inValues });
    }
    else
      throw new TargetException(string.Format("methodName {0} not found on instance", methodName));
  }

  private object ExecuteAsyncMethod(MethodInfo mi, object[] inValues)
  {
    return mi.Invoke(this.Instance, inValues);
  }

  private void FuncCallback(IAsyncResult result)
  {
    var deleg = (Func<MethodInfo, object[], object>)((AsyncResult)result).AsyncDelegate;
    var state = result.AsyncState as GenericAsyncState;
    if (null != deleg)
    {
      Exception error = null;
      object retval = null;
      try
      {
        retval = deleg.EndInvoke(result);
      }
      catch (Exception e)
      {
        error = e;
      }
      object userState = state == null ? null : state.UserState;
      string methodName = state == null ? (string)null : state.MethodName;
      object[] inValues = state == null ? null : state.InValues;
      GenericAsyncWrapperCompletedEventArgs args = new GenericAsyncWrapperCompletedEventArgs(retval, error, methodName, userState, inValues);
      if (this.AsyncCompleted != null)
        this.AsyncCompleted(this, args);
    }
  }

  private class GenericAsyncState
  {
    public object UserState { get; set; }
    public string MethodName { get; set; }
    public object[] InValues { get; set; }
  }
}

public class GenericAsyncWrapperCompletedEventArgs : EventArgs
{
  public GenericAsyncWrapperCompletedEventArgs(object result, Exception error, string methodName, object userState, object[] inValues)
  {
    this.Result = result;
    this.Error = error;
    this.MethodName = methodName;
    this.UserState = userState;
    this.InValues = inValues;
  }
  public object Result { get; private set; }
  public Exception Error { get; private set; }
  public string MethodName { get; private set; }
  public object UserState { get; private set; }
  public object[] InValues { get; private set; }
}

You can download the code here GenericUtils.zip (7.33 KB). If you find it useful, I'd love to hear from you. If you think this was a total waste of time, turn the TV back on.

Analysis Paralysis: Ten Strategies for Getting Off the Thought Pot

Do you have a hard time making decisions? Even the most decisive of us can get caught in the headlights of the oncoming project train, unable to choose left, right or straight ahead. Here’s a few strategies that I’ve found useful and sometimes forgotten about while stuck on the software development analysis thought pot.

  1. Ready, aim, fire! Research, evaluate, decide. Hesitation breeds doubt. Doubt is the father of indecision. Make a reasonable degree of confidence your standard and avoid looking for absolute guarantees. There are none.
     
  2. Put away fear of failure and accept the fact that there is more than one acceptable outcome to life’s challenges, including your project. Learn from mistakes but don’t be too afraid to make new ones.
     
  3. Begin. Make a start. Act. No journey or decision can ever be taken without the first step. Make a small decision, take action and then improve on your progress by evaluating regularly. Take digestible course correction decisions. Don’t derail your project by overcorrecting and rolling the bus at full speed.
     
  4. Set a decision deadline and stick to it. Lay out an incremental research and evaluation plan with a list of questions you need answers to in order to make your decision. If you don’t have a perfect answer, enumerate what you have anyway and incorporate it into your final decision.
     
  5. When the problem is too big and the decision too overwhelming, break it down into smaller, more specific pieces. Apply the strategies you find effective on the more manageable elements. Do that until you’ve put all the pieces together and before you know it, the puzzle will be complete.
     
  6. If the outcomes of the decision, regardless of the choice, are equally acceptable, flip a coin. Move on. Don’t waste time dwelling on equally acceptable paths to different but relatively satisfying conclusions.
     
  7. Go crazy. Make a choice even if you don’t have a reasonable level of confidence. Get off the ice berg and start swimming. Something will happen and that will lead to something else. It might turn out to have been a mistake, but at least you’ll have momentum on your side. A moving car is far easier to turn around than one that is parked.
     
  8. Put things into perspective. This project decision you’re worrying about, the one keeping you up at nights. Can it compare with watching your kid’s school play? Will your client attend your kid’s wedding? Or your funeral? Beyond successful completion or abject miserable failure on the project, will the outcome have a permanent impact on your life in the long term? Will it matter to your grandkids? Perspective can be a powerful decision making tool.
     
  9. If you can’t take the plunge off the high dive, run an experiment. Try out your decision on a smaller scale. See what happens. Take the results and boldly make the real decision.
     
  10. Change your point of view. Look for a distraction. Take a walk in a Japanese garden. See a movie. Read a good book. Take your wife on a date. Go to church. Do something to get away from it all, even if just for a few hours. Then come back with a few oxygenated brain cells and make a decision. Ready, aim, fire!

What strategies have you found useful when stuck, unable to make a critical choice on a project? I’d love to hear from you.

Update: I know these are generalized platitudes, but sometimes a good platitude can spark the inspiration one needs to find a specific solution to a real problem.