|
Thanks for sharing your ideas.
However, when I tried out the Unit Test Code presented I found that the test fails with result=0 and didComplete=false (tested when code run in the windows form). Passing value type variables to and from anonymous delegates in this way is not possible.
|
|
|
|
|
I don't think reference vs. value type has anything to do with it. To verify, I redownloaded the source and ran the tests, both pass. I'm running them with testdriven.net and nunit, what are you using?
|
|
|
|
|
Yes, you are right. It does not have anything to do with value types. It can however be dangerous to pass information that way. What I tried was to run your unit test code in a windows forms context (i.e. in your button3_clicked handler). In that synchronization context the code in whenFinished run after the handler method has finished. When running NUnit, the whenFinished code will run in the same thread as the Process code yielding the correct result every time (yes, I verified it too in NUnit).
In normal usage you would not wait for the background process to complete before leaving the calling handler, so the problem I had will not be present. You solution with passing results as an argument to the whenFinished method is a great solution.
|
|
|
|
|
If you were using this from a controller or presenter, the following code:
using (ThreadedExecuter<BusinessObject> executer =
new ThreadedExecuter<BusinessObject>(this))
{
executer
.Process(() =>
{
return GetData();
})
.WhenFinished(businessObject =>
{
UseData(businessObject);
})
.Run();
}
Would just become:
using (ThreadedExecuter<BusinessObject> executer =
new ThreadedExecuter<BusinessObject>(this))
{
executer
.Process(() =>
{
return Model.GetData();
})
.WhenFinished(businessObject =>
{
View.UseData(businessObject);
})
.Run();
}
|
|
|
|
|
|
Any particular reason or just having a bad day?
|
|
|
|
|
I looked at your user history and you have posted 0 articles and every single message of yours (save for one) is a vote of 1 or 2. I guess I'll take pride that I'm in the top tier of your voting range.
Maybe you can post an article so we can all see the excellent quality you are used to?
|
|
|
|
|
He's a well known idiot. There should be a way to reverse votes from a "griever".
Any suggestions, ideas, or 'constructive criticism' are always welcome.
"There's no such thing as a stupid question, only stupid people." - Mr. Garrison
|
|
|
|
|
Hi!
Interesting article, I’m working a MVP pattern for my application now, do you have any examples using this threadedexecuter in a MVP project?
|
|
|
|
|
There are quite a few ways to implement MVP, but in my case the button in the UI calls a method in the presenter to GetXYZ, the presenter has a reference to the view and passes that to the threaded executer call. The threaded executer method call returns immediately and once it completes it calls the method on the view to display the data retreived. I tend to write my tests on the presenter, mocking the view and the model.
I'll think about making an article for that, might be a few weeks before I get to it, but the above is the gist of it.
|
|
|
|
|
oki, nice.
I'll would really appreciate some input on the MVP I'm "making", can't get it to work as I want.
I'm trying to use MVP pattern with UserControls.
Have you any time to take a look at it? It would probably be really easy for you.
|
|
|
|
|
Sure, post an article or bog entry somewhere with where you are and what the sticking points are. My bet is that while writing it you'll see a few possible solutions, but if not I can provide some feedback.
I have a few user controls in my implementation. The controls are a part of the view so they can have methods that take business objects and when you update the view from the presenter (or model depending on how you're doing it) then you just pass that through to the control from the form code
|
|
|
|
|
Thank you very much! I'll fix it later today/night..
Don't have any blog to put it on, but I'll set up example project and some UML diagram how I like it to function.
And I'll fix a link or something for you to download from.
|
|
|
|
|
Hi Paul!
I have send you a e-mail, will all stuff in it.
It would be great if you can take alook at it.,
Thx for helping me.
|
|
|
|
|
Hi Paul!
Have had any time to take a look at the MVP I sent you?
I can't figure out how to create the MVP pattern with a usercontrol.
I would really appreciate if you had a few minutes over to check it out.
I can’t solve it.
/Ulf
|
|
|
|
|
I never got any sample files or anything.. Where can I find the files for a sample project you are working with?
|
|
|
|
|
Hi Paul!
I have fixed a new project you can check out.
you can download the file here:
http://www.easy-share.com/1903778963/MVP.rar[^]
I'm going to use 10 usercontrols in my project.. so it will be 10 timers, feels a lot?! but checkout the code and the text i added to the project and in the pdf file and you will understand what I mean.
|
|
|
|
|
RemoteObjects.ServerMotors need to be a list, not separate variables so you can iterate through them instead of referencing them one at a time
UI_Position doesn't belong in ServeroMotor.cs - separate the UI from the servo concept
I think you've made this too complicated.
Start simple with a unit test and decide how the object model should work, independent from UI. For example, the servos will be raising events to a controller.
The controller can reraise the events on a buffered schedule which is variable. You set that buffer based on what you want for the UI, i.e. every 100 events or no more than every x milliseconds, with the last received servo event per servo and the view then displays that info based on those buffered events.
The below is what you should get working first in a threaded manner, without worrying about the UI. Once that is working then it should be pretty simple to just hook the UI into the buffered events using the presenter to listen to these.
namespace ExampleDesign
{
public class Test
{
public void RunTest()
{
List<ServoMotor> motors = new List<ServoMotor>();
motors.Add(new ServoMotor("Motor1"));
motors.Add(new ServoMotor("Motor2"));
motors.Add(new ServoMotor("Motor3"));
//your presenter could use this controller to listen and send data to the UI on the buffered update
ServoMotorController controller = new ServoMotorController(motors, 25);
controller.BufferedUpdated += delegate()
{
foreach (ServoMotor motor in motors)
{
Console.WriteLine(motor.Name + ": " + motor.Property1);
}
};
HardwareSimulator simulator = new HardwareSimulator(motors, 100, 10);
simulator.Run();
}
}
public class ServoMotorController
{
public ServoMotorController(IEnumerable<ServoMotor> motors, int bufferCount)
{
foreach(ServoMotor motor in motors)
motor.HardwareUpdated += new ServoMotor.HardwareUpdatedDelegate(motor_HardwareUpdated);
this.bufferCount = bufferCount;
}
int bufferCount = 0;
int events = 0;
public delegate void BufferedUpdatedDelegate();
public event BufferedUpdatedDelegate BufferedUpdated;
void motor_HardwareUpdated()
{
events++;
//only raise every bufferCount events
if (events % bufferCount == 0)
{
BufferedUpdated();
}
}
}
public class ServoMotor
{
public ServoMotor(string name)
{
this.Name = name;
}
private string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
private int _Property1;
public int Property1
{
get { return _Property1; }
set { _Property1 = value; }
}
public delegate void HardwareUpdatedDelegate();
public event HardwareUpdatedDelegate HardwareUpdated;
public void Update(object someData) //not object, something else with whatever data
{
Property1 = new Random().Next();
if(HardwareUpdated != null)
HardwareUpdated();
}
}
public class HardwareSimulator
{
public HardwareSimulator(IEnumerable<ServoMotor> motors, int eventCount, int delayMilliseconds)
{
this.motors = motors;
this.eventCount = eventCount;
this.delayMilliseconds = delayMilliseconds;
}
IEnumerable<ServoMotor> motors = null;
int eventCount;
int delayMilliseconds;
public void Run()
{
for (int i = 0; i < eventCount; i++)
{
foreach (ServoMotor motor in motors)
{
motor.Update("Some stuff");
}
Thread.Sleep(delayMilliseconds);
}
}
}
}
|
|
|
|
|
Hi Paul!
Thx for the input..
I'm looking at the code just now, great!!
I'll get back to you when I have checked out the code a little bit more.
One question, you have used a more event based approach then a timer approach, does that works as good as using a timer that is polling values?
What I mean is, does the event execute as precise as a timer polling, the timer does always get values within a certain timeframe, but how good is the event stuff at this?
I’m just curious, it may even be better than the timer approach?
And your ServoMotorController class is the model then in the MVP?
modified on Sunday, March 15, 2009 7:58 AM
|
|
|
|
|
The event executes whenever you call it. You would still use your timer, but fire the event in the timer instead of doing work. That makes it easier to test and understand.
|
|
|
|
|
oki, I'm new to this seperating stuff, so sorry for all dumb questions.
So my model class should still have the timer then?
I'm not sure how I should create the presenter, should I use one presenter for all usercontrols?
I like to do something like this in the form.
private void Form1_Load(object sender, EventArgs e)
{
this._servoPresenter = new ServoPresenter();
this._servoModel = new ServoModel();
this.ucServo1.WireUp(this._servoModel, this._servoPresenter, RemoteObjects.ServoMotor1);
this.ucServo2.WireUp(this._servoModel, this._servoPresenter, RemoteObjects.ServoMotor2);
}
And in the usercontrol:
public void WireUp(IServoModel servoModel, IServoPresenter servoPresenter, ServoMotor servoMotor)
{
this.ServoModel = servoModel;
this.ServoPresenter = servoPresenter;
this._servoMotor = servoMotor;
this.ServoModel.AddServo(servoMotor, this);
}
And in the model or something..:
private Dictionary<string, ServoMotor> _servoList = new Dictionary<string, ServoMotor>();
private Dictionary<string, INotify> _notifyList = new Dictionary<string, INotify>();
'
public ServoModel(int bufferCount)
{
this._bufferCount = bufferCount;
}
private int _bufferCount = 0;
private int _events = 0;
public delegate void BufferedUpdatedDelegate();
public event BufferedUpdatedDelegate BufferedUpdated;
private void ServoUpdated()
{
this._events++;
//only raise every bufferCount events
if (this._events % this._bufferCount == 0)
{
BufferedUpdated();
}
}
public void AddServo(ServoMotor servo, INotify notifier)
{
if (this._servoList.ContainsKey(servo.Name) == false)
{
servo.ServoUpdated += new ServoMotor.ServoUpdatedDelegate(ServoUpdated);
this._servoList.Add(servo.Name, servo);
this._notifyList.Add(servo.Name, notifier);
}
}
modified on Sunday, March 15, 2009 11:22 AM
|
|
|
|
|
No, start with one presenter, one view and one model that just works for one servo. Get that working, then refactor to a user control if needed when you do multiple servos. You may nor may not need an additional presenter for that. If the control just deals with UI things then you can just use the presenter for the original the view and be done.
|
|
|
|
|
Now I have fixed some code for you to checkout, if you have the time of course.
This Is what I have done.
I have created two different MVP patterns.
1: MVP Remoting: This is for remoting .net (in remoting the event stuff shouldn’t be used, so I use the polling approach here)
2: MVP (local): No remoting here, so I tried to use your event approach
Can you check out my code so I haven't done any design "faults" and stuff like that?
Thx Paul for all your help, I really appreciate all the help you give me.
You should write an article on the MVP with usercontrols and responsive UI
You can find the new code at:
http://www.easy-share.com/1904053631/MVP.rar[^]
Start project and press Button1 for the postion values and press On,Off buttons for turning on/off servo
modified on Tuesday, March 17, 2009 6:44 AM
|
|
|
|
|
Hi Paul!
Have had any time to take a look at the MVP pattern?
I desperately need some input how I should structure the pattern, Is it good way to go with a timer for each usercontrols? Or is it better to only use one timer for all usercontrols, and if I should use one, how should I design it? I have only got it to work with one timer for each usercontrol.
I would really appreciate your input on this, abit new on the area.
thx
|
|
|
|
|
I never got any sample files or anything.. Where can I find the files for a sample project you are working with?
|
|
|
|