• Products
  • Solutions
  • Resources
  • Partners
  • About Us
  • Contact Us

Damon Lockwood

Ouch, over a year?

by Damon Lockwood on October 28, 2011

Can’t believe it’s been over a year since I posted. Things were busy. So here’s the latest:I’m now CTO of OpenSpan. I’ve taken on a lot of additional responsibilities around product strategy and customers, which leads to…Stephen is now Chief Scientis…

{ Comments on this entry are closed }

Ouch, over a year?

by Damon Lockwood on October 28, 2011

Can’t believe it’s been over a year since I posted. Things were busy. So here’s the latest:

I’m now CTO of OpenSpan. I’ve taken on a lot of additional responsibilities around product strategy and customers, which leads to…

Stephen is now Chief Scientist. He’s officially the undisputed god of the deep, dark, awesome, unfathomable underpinnings or our technology and is devoting himself full-time to internals and RE, which leads to…

Danny is now VP of Development. He’s taking over running our team operationally, delivering release and all that good stuff, which leads to…

We’re growing and we’re hiring. If you’re a data guru (NoSQL, MySQL, Hadoop) or a cloud guru (Ruby, AWS) or a web guru (HTML, jQuery, CSS) or a reverse engineering guru (injection, hooking, disassembly) let me know!

{ Comments on this entry are closed }

Handling web pages that navigate back to themselves

by Damon Lockwood on May 5, 2010

I recently worked through a customer issue that revolved around a page that reloaded itself when a form was submitted. This is a pretty common scenario, but it can be a little tricky to handle in OpenSpan, especially if the reloaded page doesn’t actually create any new elements to wait upon. The trick is to wait for the Destroyed event to fire on the web page after you call the method that triggers the reload. This is pretty easy to do in an automation by using the “Wait for this event” feature.

First, drag the Destroyed event from the page onto the automation surface. Right click and select for “Wait for this event”. The event will now transform into an object you can wait for.


Selecting the “Wait for this event” command
Next, connect the Setup port to the method that will trigger the reload, in this case the PerformClick method.


The right way to trigger the event.

Note, you must use the Setup port to ensure that OpenSpan is ready to wait for the event when you trigger it. If you call PerformClick before you enter the event block there is always the chance that the Destroyed event will fire between the two blocks in which case the event will be missed.


The wrong way to trigger the event.

Finally, connect the Fired port to the blocks that should execute after the page has reloaded.


The complete solution.

As you can see, waiting for an event is very easy in an automation, but how would you accomplish the same thing in code? You could spin your own eventing mechanism, but this would be a fair amount of work and require a good knowledge of threading. Fortunately there is another way to access the wait for event functionality. Every OpenSpan control supports a GetEvent method which takes a special EventName object. This method actually pre-dates the automation “Wait for this event” functionality. GetEvent takes a parameter of type EventName which is simply a wrapper around the name of the event. GetEvent returns an Event object which exposes a Wait method. Events objects are managed internally by the control so you do not have to worry about disposing the object. The following code snippet illustrates how to use GetEvent.


public void DoSearch()
{
// Get event
Event waitForDestroy = mSample.EventSamplePage.GetEvent(new EventName("Destroyed"));

// Perform click
mSample.Next.PerformClick();

// Wait for event
if (waitForDestroy.WaitForEvent(10000))
{
// Next steps
}
else
{
// Handle error
}
}

{ Comments on this entry are closed }

Handling web pages that navigate back to themselves

by Damon Lockwood on May 5, 2010

I recently worked through a customer issue that revolved around a page that reloaded itself when a form was submitted. This is a pretty common scenario, but it can be a little tricky to handle in OpenSpan, especially if the reloaded page doesn’t actually create any new elements to wait upon. The trick is to wait for the Destroyed event to fire on the web page after you call the method that triggers the reload. This is pretty easy to do in an automation by using the “Wait for this event” feature.

First, drag the Destroyed event from the page onto the automation surface. Right click and select for “Wait for this event”. The event will now transform into an object you can wait for.


Selecting the “Wait for this event” command
Next, connect the Setup port to the method that will trigger the reload, in this case the PerformClick method.


The right way to trigger the event.

Note, you must use the Setup port to ensure that OpenSpan is ready to wait for the event when you trigger it. If you call PerformClick before you enter the event block there is always the chance that the Destroyed event will fire between the two blocks in which case the event will be missed.


The wrong way to trigger the event.

Finally, connect the Fired port to the blocks that should execute after the page has reloaded.


The complete solution.

As you can see, waiting for an event is very easy in an automation, but how would you accomplish the same thing in code? You could spin your own eventing mechanism, but this would be a fair amount of work and require a good knowledge of threading. Fortunately there is another way to access the wait for event functionality. Every OpenSpan control supports a GetEvent method which takes a special EventName object. This method actually pre-dates the automation “Wait for this event” functionality. GetEvent takes a parameter of type EventName which is simply a wrapper around the name of the event. GetEvent returns an Event object which exposes a Wait method. Events objects are managed internally by the control so you do not have to worry about disposing the object. The following code snippet illustrates how to use GetEvent.


public void DoSearch()
{
// Get event
Event waitForDestroy = mSample.EventSamplePage.GetEvent(new EventName("Destroyed"));

// Perform click
mSample.Next.PerformClick();

// Wait for event
if (waitForDestroy.WaitForEvent(10000))
{
// Next steps
}
else
{
// Handle error
}
}

{ Comments on this entry are closed }

Hosting OpenSpan: A complete ISynchronizeInvoke wrapper for the Dispatcher

by Damon Lockwood on April 21, 2010

As I mentioned in my last post, I’ve been working on a sample where I host OpenSpan adapters inside of a WPF Prism application. Here’s a screenshot that will help give you a sense of it.When I started fleshing out the sample, I realized that WPF didn’t…

{ Comments on this entry are closed }

Hosting OpenSpan: A complete ISynchronizeInvoke wrapper for the Dispatcher

by Damon Lockwood on April 21, 2010

As I mentioned in my last post, I’ve been working on a sample where I host OpenSpan adapters inside of a WPF Prism application. Here’s a screenshot that will help give you a sense of it.


When I started fleshing out the sample, I realized that WPF didn’t provide an object that implemented ISynchronizeInvoke that I could pass to the adapter Start method. As a little background, we added an overload to the Start method that takes an instance of ISynchronizeInvoke as a convenience for developers using adapters within windows forms applications. Normally, within the OpenSpan runtime, adapters fire asynchronous events on thread pool threads. Our automation surface abstracts the invocations required to interact with windows forms from visual developers.

When hosting adapters directly in .NET, we quickly realized that it was painful to force developers to invoke onto the windows forms thread anytime they needed to update their UI within an adapter event. Thus, we added an overload to the Start method where developers could pass in an instance of ISynchronizeInvoke. In practice, since all windows forms controls implement ISynchronizeInvoke, developers simply pass in their form or user control. When an adapter is started with an instance of ISynchronizeInvoke, it will automatically invoke all events onto the right thread.

However, the WPF Dispatcher object, which provides equivalent functionality to ISynchronizeInvoke, does not actually implement ISynchronizeInvoke. A quick search revealed that other folks had run into the same issue with WPF and created wrappers. However, looking over the wrappers, they weren’t entirely complete. It seems that nobody had implemented every method or property required. In particular I knew that our adapters depended on the EndInvoke method and the IAsyncResult.AsyncWaitHandle property.

To remedy this, I implemented my own wrapper. In addition to the public DispatchWrapper, I created a couple of nested private classes, DispatchOperationWrapper and DispatcherOperationWaitHandle, to hide the IAsyncResult and WaitHandle implementation details. Unlike some of the samples I found the implementation below doesn’t use any looping or sleeps to wait. Also note that the implementation for IAsyncResult.CompletedSynchronously always return false. This conforms to the IAsyncResult guidance on MSDN.


using System;
using System.Threading;
using System.Windows.Threading;

namespace OpenSpan.Samples
{
public class DispatcherWrapper : ISynchronizeInvoke
{
private Dispatcher _Dispatcher;

public DispatcherWrapper(Dispatcher dispatcher)
{
_Dispatcher = dispatcher;
}

#region ISynchronizeInvoke Members
public IAsyncResult BeginInvoke(Delegate method, object[] args)
{
DispatcherOperation op = _Dispatcher.BeginInvoke(method, args);
return new DispatcherOperationWrapper(op);
}

public object EndInvoke(IAsyncResult result)
{
DispatcherOperationWrapper wrapper = result as DispatcherOperationWrapper;
if (wrapper != null)
{
wrapper.Operation.Wait();
return wrapper.Operation.Result;
}
throw new ArgumentException("Result does not wrap a DispatchOperation");
}

public object Invoke(Delegate method, object[] args)
{
return _Dispatcher.Invoke(method, args);
}

public bool InvokeRequired
{
get { return _Dispatcher.CheckAccess(); }
}

#endregion

private class DispatcherOperationWrapper : IAsyncResult
{
private DispatcherOperationWaitHandle _WaitHandle;
private DispatcherOperation _Operation;
private object _State;

public DispatcherOperationWrapper(DispatcherOperation operation)
{
_Operation = operation;
}

public DispatcherOperationWrapper(DispatcherOperation operation, object state)
: this(operation)
{
_State = state;
}

public DispatcherOperation Operation
{
get
{
return _Operation;
}
}

#region IAsyncResult Members
public object AsyncState
{
get { return _State; }
}

public WaitHandle AsyncWaitHandle
{
get
{
if (_WaitHandle == null)
{
_WaitHandle = new DispatcherOperationWaitHandle(_Operation);
}
return _WaitHandle;
}
}

public bool CompletedSynchronously
{
get { return false; }
}

public bool IsCompleted
{
get { return (_Operation.Status == DispatcherOperationStatus.Completed); }
}
#endregion

private class DispatcherOperationWaitHandle : WaitHandle
{
private DispatcherOperation _Operation;

public DispatcherOperationWaitHandle(DispatcherOperation operation)
{
_Operation = operation;
}

public override bool WaitOne()
{
DispatcherOperationStatus status = _Operation.Wait();
return (status == DispatcherOperationStatus.Completed);
}

public override bool WaitOne(int milliseconds)
{
return this.WaitOne(new TimeSpan(0, 0, 0, 0, milliseconds));
}

public override bool WaitOne(int milliseconds, bool exitContext)
{
return WaitOne(milliseconds);
}

public override bool WaitOne(TimeSpan timeout)
{
DispatcherOperationStatus status = _Operation.Wait(timeout);
return (status == DispatcherOperationStatus.Completed);
}

public override bool WaitOne(TimeSpan timeout, bool exitContext)
{
return this.WaitOne(timeout);
}
}
}
}
}

{ Comments on this entry are closed }

← Previous Entries

  • Follow Us!

    Follow Us on FacebookFollow Us on Google+Follow Us on TwitterFollow Us on LinkedInFollow Us on YouTubeFollow Us on RSS

    By PDGACO payday loan

  • Search

  • Recent Posts

    • What If You Could Eliminate Post-Call Wrap-Up?
    • The Agent Desktop and its Strategic Role in Contact Center Performance
    • Going Beyond Agile Development for Claims Automation
  • Categories

  • Archives

Get smart with the Thesis WordPress Theme from DIYthemes.

WordPress Admin