|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Collections;
using System.Threading;
namespace ThreadingComponent
{
/// <summary>
/// A simple demo viewmodel that contains a single
/// <see cref="ThreadableItemViewModel">ThreadableItemViewModel</see>
/// that returns a List of <see cref="StuffData">StuffData</see>.
///
/// This class contains some TESTING/SIMULATION code that is clearly marked, and described
/// This TESTING/SIMULATION code MUST be removed for your real production code. It is
/// here merely to demomstrate how the Adorners work when there is a Failure during the
/// background threading operation
/// </summary>
public class Window1ViewModel : ViewModelBase
{
#region Data
private ICommand runCommand;
private ThreadableItemViewModel<List<StuffData>> threadVM =
new ThreadableItemViewModel<List<StuffData>>();
#endregion
/// Pay very special attention to the code sections marked with
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// FOR TESTING ONLY
#region Constructor
public Window1ViewModel()
{
//This is the threading payload delegate that will be called when the background thread
//is run. This is the only thing that should need to change each time, apart from
//specifiying the generic T for the ThreadableItemViewModel<T>
Func<Dictionary<String, Object>, ThreadableItem<List<StuffData>>> taskFunc = (inputParams) =>
{
try
{
// REGION BELOW FOR TESTING ONLY
// REGION BELOW FOR TESTING ONLY
// REGION BELOW FOR TESTING ONLY
// REGION BELOW FOR TESTING ONLY
// REGION BELOW FOR TESTING ONLY
//
// You would replace the example regions code below with something specific to your
// actual app domain requirements, for example here is what one of our actual
// production code methods (this is assuming we are using a WCF
// service to provide the data) may look like :
//
//try
//{
// //Obtain a list of Clients that work in particular BusinessArea
// Service<IGateway>.Use((client) =>
// {
// RetrieveDataByQueryRequest request = new RetrieveDataByQueryRequest();
// request.Query = new Query().SelectAll(BusinessEntityType.Client)
// .Where(new Filter("BusinessAreaId",
// FieldOpeartor.Equals,(Int32)inputParams["businessArea"]);
// RetrieveDataByQueryResponse response =
// (RetrieveDataByQueryResponse)client.Execute(request);
// return new ThreadableItem<List<Client>>(response.Clients, String.Empty);
// });
//}
////catch WCF FaultExceptions
//catch (FaultException<SerializationException> sex)
//{
// //throw actual Exception which is caught it outer catch
// throw new BusinessException("A serialization issue has occurred");
//}
////catch WCF FaultExceptions
//catch (FaultException<InvalidArgumentException> iaex)
//{
// //throw actual Exception which is caught it outer catch
// throw new BusinessException("One of the arguments is invalid");
//}
#region TEST EXAMPLE CODE, YOU SHOULD NOT DO THIS IN PRODUCTION CODE
if (ShouldFail)
{
throw new InvalidOperationException(
"InvalidOperationException occurred\r\n\r\n" +
"This Exception has been raised inside the Window1ViewModel delegate " +
"which is the actual payload for the ThreadableItemViewModel<T> TaskFunc delegate.\r\n\r\n" +
"Which is obvioulsy not what you would do in a production system.\r\n\r\n" +
"You would more typically catch your own business Exceptions " +
"(say from talking to WCF) and then rethrow them. " +
"This just demomstrated how all this hangs together");
}
else
{
List<StuffData> data = new List<StuffData>();
for (int i = 0; i < (Int32)inputParams["loopMax"]; i++)
{
data.Add(new StuffData(String.Format("The Text Is {0}",i),i));
Thread.Sleep(5); //simulate time going by
}
//work is done at this point, so return new ThreadableItem with the
//actual data in it, and no failure message
return new ThreadableItem<List<StuffData>>(data, String.Empty);
}
#endregion
}
//something went wrong so return a new ThreadableItem with the failed
//message in it
catch(Exception ex)
{
return new ThreadableItem<List<StuffData>>(null, ex.Message);
}
};
//setup Threading task function
threadVM.TaskFunc = taskFunc;
//setup Threading parameters
Dictionary<String, Object> parameters = new Dictionary<String, Object>();
parameters.Add("loopMax", 1000);
threadVM.Parameters = parameters;
runCommand = new SimpleCommand
{
CanExecuteDelegate = x => !threadVM.IsBusy,
ExecuteDelegate = x => { threadVM.Run(); }
};
/// <summary>
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// FOR TESTING ONLY
///
/// YOU NEED TO DELETE THIS IN YOUR PRODUCTION CODE
/// YOU NEED TO DELETE THIS IN YOUR PRODUCTION CODE
/// YOU NEED TO DELETE THIS IN YOUR PRODUCTION CODE
/// YOU NEED TO DELETE THIS IN YOUR PRODUCTION CODE
/// YOU NEED TO DELETE THIS IN YOUR PRODUCTION CODE
/// </summary>
shouldFailCommand = new SimpleCommand
{
CanExecuteDelegate = x => !threadVM.IsBusy,
ExecuteDelegate = x => { ShouldFail = !ShouldFail; }
};
}
#endregion
#region Public Properties
public ThreadableItemViewModel<List<StuffData>> ThreadVM
{
get { return threadVM; }
}
public ICommand RunCommand
{
get { return runCommand; }
}
#endregion
///This is simulation code and is only here to demonstrate how
///the control works with a Failure. You should remove this code
///within a production environment
///
/// YOU NEED TO DELETE THIS IN YOUR PRODUCTION CODE
/// YOU NEED TO DELETE THIS IN YOUR PRODUCTION CODE
/// YOU NEED TO DELETE THIS IN YOUR PRODUCTION CODE
/// YOU NEED TO DELETE THIS IN YOUR PRODUCTION CODE
/// YOU NEED TO DELETE THIS IN YOUR PRODUCTION CODE
#region SIMULATION CODE : THIS SHOULD BE REMOVED IN PRODUCTION CODE
/// <summary>
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// </summary>
private ICommand shouldFailCommand;
/// <summary>
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// </summary>
public ICommand ShouldFailCommand
{
get { return shouldFailCommand; }
}
/// <summary>
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// </summary>
private Boolean shouldFail = false;
/// <summary>
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// FOR TESTING ONLY
/// </summary>
public bool ShouldFail
{
get { return shouldFail; }
set
{
shouldFail = value;
NotifyPropertyChanged("ShouldFail");
}
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)
- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence
Both of these at Sussex University UK.
Award(s)
I am lucky enough to have won a few awards for Zany Crazy code articles over the years
- Microsoft C# MVP 2016
- Codeproject MVP 2016
- Microsoft C# MVP 2015
- Codeproject MVP 2015
- Microsoft C# MVP 2014
- Codeproject MVP 2014
- Microsoft C# MVP 2013
- Codeproject MVP 2013
- Microsoft C# MVP 2012
- Codeproject MVP 2012
- Microsoft C# MVP 2011
- Codeproject MVP 2011
- Microsoft C# MVP 2010
- Codeproject MVP 2010
- Microsoft C# MVP 2009
- Codeproject MVP 2009
- Microsoft C# MVP 2008
- Codeproject MVP 2008
- And numerous codeproject awards which you can see over at my blog