I have class that draw three types of charts, and i want to update it by function public void GetData(PlotModel PlotModel). The main problem is that every series (AreaSeries,CandleStickSeries,HighLowSeries) has different interfaces. How can i update different types in function public void GetData(PlotModel PlotModel). What should i use Activator? Generic?
I think that something like is bad idea:
public void GetData(PlotModel PlotModel) {
while(true) {
System.Threading.Thread.Sleep(1000);
// Add new Item?
switch(PlotModel.Series.First().ToString()) {
case "OxyPlot.Series.AreaSeries":
Console.WriteLine("AreaSeries");
break;
case "OxyPlot.Series.CandleStickSeries":
Console.WriteLine("CandleStickSeries");
break;
case "OxyPlot.Series.HighLowSeries":
Console.WriteLine("HighLowSeries");
break;
}
}
}
Code:
namespace WpfApplication20 {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
///
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
DataContext = new PlotClass();
}
}
public class PlotClass {
public PlotModel PlotModel { get; set; }
public PlotClass() {
PlotModel = new PlotModel();
DrawCandleChart(PlotModel);
UpdateChartAsync(PlotModel);
}
public void DrawSimpleChart(PlotModel PlotModel) {
Random rnd = new Random();
LineSeries LS = new LineSeries();
for (int i=0;i<10;i++) {
LS.Points.Add(new DataPoint(i,rnd.NextDouble()));
}
PlotModel.Series.Add(LS);
PlotModel.InvalidatePlot(false);
}
public void DrawCandleChart(PlotModel PlotModel) {
Random rnd = new Random();
CandleStickSeries CSS = new CandleStickSeries();
for (int i=0;i<10;i++) {
CSS.Items.Add(new HighLowItem { Close = rnd.NextDouble(), High = rnd.NextDouble(), Low = rnd.NextDouble(), Open = rnd.NextDouble(), X = i });
}
PlotModel.Series.Add(CSS);
PlotModel.InvalidatePlot(false);
}
public void DrawHighLowChart(PlotModel PlotModel) {
Random rnd = new Random();
HighLowSeries HLS = new HighLowSeries();
for (int i = 0; i < 10; i++) {
HLS.Items.Add(new HighLowItem { Close = rnd.NextDouble(), High = rnd.NextDouble(), Low = rnd.NextDouble(), Open = rnd.NextDouble(), X = i });
}
PlotModel.Series.Add(HLS);
PlotModel.InvalidatePlot(false);
}
public void UpdateChartAsync(PlotModel PlotModel) {
Action<PlotModel> Update = new Action<PlotModel>(GetData);
IAsyncResult result = Update.BeginInvoke(PlotModel, null, null);
}
public void GetData(PlotModel PlotModel) {
while(true) {
System.Threading.Thread.Sleep(1000);
// Add new Item?
}
}
}
}
C# 4 and up offers a nice way of processing situations like this: use cast to dynamic, and call a method with one overload per subtype, like this:
private void Process(AreaSeries arSer) {
...
}
private void Process(CandleStickSeries csSer) {
...
}
private void Process(HighLowSeries hlSer) {
...
}
...
while(true) {
System.Threading.Thread.Sleep(1000);
Process((dynamic)PlotModel.Series.First());
// ^^^^^^^^^
}
The cast to dynamic makes the "magic" happen: C# will examine the run-time type of PlotModel.Series.First(), and dispatch to one of the three Process methods that you supplied.
There is a danger in this approach: if PlotModel.Series.First() happens to not match any of the overloads, you get a run-time exception. The compiler cannot perform static analysis to tell you that your call would not succeed. Consider adding a catch-all method for the common superclass of your plots, too, so that you could handle unexpected sub-types more gracefully.
Related
Given a situation where I have a method SetFooInDevice(), which I call using a property as one of the arguments:
public class Program
{
public static byte Foo { get; set; }
public static void SetFooInDevice(System.IO.Ports.SerialPort sp, byte foo)
{
var txBuffer = new List<byte>();
// Format message according to communication protocol
txBuffer.Add(foo);
sp.Write(txBuffer.ToArray(), 0, txBuffer.Count);
}
public static void Main()
{
var _rnd = new Random();
var _serialPort = new System.IO.Ports.SerialPort("COM1", 9600);
_serialPort.Open();
for (int i = 0; i < 100; i++)
{
Foo = (byte)_rnd.Next(0, 255);
SetFooInDevice(_serialPort, Foo); // <-- How to add this call to a collection?
System.Threading.Thread.Sleep(100);
}
}
}
Is it possible to add the method call to a collection, in a way that the method call can be executed when running through the collection at a later time?
I want to be able to add calls to various methods to a collection, that I can run through and execute later if conditions are met (serial port open, time interval has passed, etc.).
Try this:
public static byte Foo { get; set; }
public static void SetFooInDevice(System.IO.Ports.SerialPort sp, byte foo)
{
var txBuffer = new List<byte>();
// Format message according to communication protocol
txBuffer.Add(foo);
sp.Write(txBuffer.ToArray(), 0, txBuffer.Count);
}
public static void Main()
{
List<Action> listActions = new List<Action>(); // here you create list of action you need to execute later
var _rnd = new Random();
var _serialPort = new System.IO.Ports.SerialPort("COM1", 9600);
_serialPort.Open();
for (int i = 0; i < 100; i++)
{
Foo = (byte)_rnd.Next(0, 255);
var tmpFoo = Foo; // wee need to create local variable, this is important
listActions.Add(() => SetFooInDevice(_serialPort, tmpFoo));
System.Threading.Thread.Sleep(100);
}
foreach (var item in listActions)
{
item(); // here you can execute action you added to collection
}
}
You can check this on MS docs Using Variance for Func and Action Generic Delegates
You can use Action delegate for this purpose like below
private List<Action<System.IO.Ports.SerialPort, byte>> methodCalls
= new List<Action<System.IO.Ports.SerialPort, byte>>();
I am working on a cardgame conform the MVVM pattern. My model contains the players, hands and cards as well as the game with its rules.
There are 2 classes not playing nice here: the "card" class that has a "submitted" event: when a player clicks on an image of the card, among other things the submitted event fires. This triggers the UI to move the card from a hand to the center of the window.
Next I have a class "trick", that all players add a card to. When the trick is full, it fires the TrickFull event: this triggers the UI to show the cards in the trick and then clear the table.
During gameplay the TrickFull event fires nanoseconds after the last card was submitted. This means the table is cleared before the 4th card can be shown. I would like to be able to force the UI to process the cardsubmitted event before the Trickfull event.
I have tried to accomplish this by Thread.Sleep (which does not work), I have also tried to move the TrickFull event to the gameclass (meaning it gets triggered much later). This works, but it does seem very out of place. I have looked into locking the events (but that does not seem to be the way to go), directly taking to control of the Dispatcher, changing the priority, or maybe calling the events asynchonously and blocking the stuff somehow in the EndInvoke.
I would like to know what the best solution for this would be. My research suggests that maybe Events would not be the best pattern for this behaviour, but I am stumped. Can you bright people please advise me on how to fix this (probably architectural) flaw?
Code below, beware: Dutch classnames and stuff in there
Card (=Kaart)
public class Kaart : IComparable<Kaart>
{
public readonly Kleur Kleur;
public readonly Waarde Waarde;
public Kaart(Kleur kleur, Waarde waarde)
{
Kleur = kleur;
Waarde = waarde;
}
public event KaartGespeeld Opgegooid;
public delegate void KaartGespeeld(Kaart kaart);
public void Opgooien()
{
Opgegooid?.Invoke(this);
}
public int CompareTo(Kaart other)
{
var comparer = new KlaverjasComparer(null, null);
return comparer.Compare(this, other);
}
public Speler Speler { get; set; }
}
Trick (=Slag)
public class Slag
{
private readonly List<Kaart> _kaarten;
[Browsable(false)]
public IReadOnlyList<Kaart> Kaarten => _kaarten;
public Slag(Kleur troef)
{
_kaarten = new List<Kaart>(4);
Troef = troef;
}
public Speler Winnaar { get; private set; }
public int Punten => PuntenTeller.Punten(this);
public int Roem => PuntenTeller.Roem(this);
[Browsable(false)]
public Kleur Troef { get; }
public Kleur GevraagdeKleur { get; set; }
[Browsable(false)]
public bool Vol =>_kaarten.Count == 4;
public void Add(Kaart kaart)
{
if (!Vol)
{
if (_kaarten.Count == 0)
{
GevraagdeKleur = kaart.Kleur;
}
_kaarten.Add(kaart);
}
else
{
throw new Exception("Te veel kaarten in een slag");
}
if (!Vol) return;
Winnaar = bepaalHoogsteKaart(this).Speler;
VolleSlag?.Invoke(this);
}
public event SlagIsVol VolleSlag;
public delegate void SlagIsVol(Slag slag);
}
ViewModel:
public TafelViewModel(Boompje boompje)
{
Speler1 = boompje.Deelnemers[0];
Speler2 = boompje.Deelnemers[1];
Speler3 = boompje.Deelnemers[2];
Speler4 = boompje.Deelnemers[3];
Troef = boompje.Potje.Troef;
//boompje.SlagIsVol += Boompje_SlagIsVol;
// ToDo: als ik naar dit event kijk gaat het mis
boompje.Potje.Slag.VolleSlag += Boompje_SlagIsVol;
boompje.Potje.TroefGedraaid += delegate { Troef = boompje.Potje.Troef; };
foreach (Speler _deelnemer in boompje.Deelnemers)
{
foreach (Kaart _kaart in _deelnemer.Hand)
{
_kaart.Opgegooid += moveKaart;
}
_deelnemer.DoeIkHet += DeelnemerOnDoeIkHet;
}
_spelerKaart = new Dictionary<Speler, string>
{
{Speler1, "Kaart1"},
{Speler2, "Kaart2"},
{Speler3, "Kaart3"},
{Speler4, "Kaart4"}
};
_spelerRichting = Dictionary.SpelersRichting(boompje.Deelnemers);
WinnaarVisible = Visibility.Hidden;
}
private void Boompje_SlagIsVol(Slag slag)
{
WinnaarVisible = Visibility.Visible;
Richting = _spelerRichting[slag.Winnaar];
Application.DoEvents();
Thread.Sleep(2000);
Kaart1 = null;
Kaart2 = null;
Kaart3 = null;
Kaart4 = null;
WinnaarVisible = Visibility.Hidden;
}
private void moveKaart(Kaart kaart)
{
PropertyInfo prop = GetType().GetProperty(_spelerKaart[kaart.Speler]);
prop?.SetValue(this, kaart);
}
public void OpKaartGeklikt(Kaart kaart)
{
if (kaart.Speler != Speler3)
{
return;
}
Speler3.SpeelKaart(kaart);
}
}
}
Set ManualResetEvent in your ViewModel
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
Pass this object into Kaart of yours
ManualResetEvent _manualResetEvent;
public Kaart(Kleur kleur, Waarde waarde, ManualResetEvent manualResetEvent)
{
Kleur = kleur;
Waarde = waarde;
_manualResetEvent = manualResetEvent;
}
This is the method that's being invoked when card is added I assume
public void Opgooien()
{
Opgegooid?.Invoke(this);
_manualResetEvent.Set();
}
And the main part (you also need to pass ManualResetEvent to the Slag object.
public void Add(Kaart kaart)
{
if (!Vol)
{
if (_kaarten.Count == 0)
{
GevraagdeKleur = kaart.Kleur;
}
_kaarten.Add(kaart);
}
else
{
throw new Exception("Te veel kaarten in een slag");
}
if (!Vol) return;
Winnaar = bepaalHoogsteKaart(this).Speler;
var result = _manualResetEvent.WaitOne(TimeSpan.FromSeconds(5));
if(!result)
{
/* Did not receive signal in 5 seconds */
}
VolleSlag?.Invoke(this);
_manualResetEvent.Reset();
}
Just the basic concept, it might not work right away due to your code language and lack of some part of it in the example, but you should catch the idea
I have a problem which i don't know how to solve.
I have some classes (Processors) that fires an event with progress information ( Percentage of how far it is). There are multiple processors that do this and the top Processor (Engine) which calls them all needs to send information to the end user on its progress.
If i don't know beforehand how many items will be processed by each processor how can i give the user some good feedback on how far the process is?
Take a look at the following simplified example
NetFiddle
class Program {
static void Main(string[] args) {
var p = new Program();
p.Run();
}
private void Run() {
var engine = new Engine();
engine.UpdateProgress += Engine_UpdateProgress;
engine.Process();
Console.ReadLine();
}
private void Engine_UpdateProgress(object sender, UpdateProgressEventArgs e) {
Console.WriteLine($"{e.UpdateDateTime} - Caller: {e.Caller}, Percentage: {e.Percentage}");
}
}
public class Engine {
private readonly ProcessorA _processorA;
private readonly ProcessorB _processorB;
private readonly ProcessorC _processorC;
private readonly ProcessorD _processorD;
public event EventHandler<UpdateProgressEventArgs> UpdateProgress;
public Engine() {
_processorA = new ProcessorA();
_processorB = new ProcessorB();
_processorC = new ProcessorC();
_processorD = new ProcessorD();
//Handle events
_processorA.UpdateProgress += ProcessorA_UpdateProgress;
_processorB.UpdateProgress += ProcessorA_UpdateProgress;
_processorC.UpdateProgress += ProcessorA_UpdateProgress;
_processorD.UpdateProgress += ProcessorA_UpdateProgress;
}
private void ProcessorA_UpdateProgress(object sender, UpdateProgressEventArgs e) {
OnUpdateProgress(e);
}
public void Process() {
_processorA.Process();
_processorB.Process();
_processorC.Process();
_processorD.Process();
}
protected virtual void OnUpdateProgress(UpdateProgressEventArgs e) {
UpdateProgress?.Invoke(this, e);
}
}
public class ProcessorA : Processor {
private readonly ProcessorA_A _processorA_A;
public ProcessorA() {
_processorA_A = new ProcessorA_A();
//Handle events
_processorA_A.UpdateProgress += ProcessorA_A_UpdateProgress;
}
public void Process() {
_processorA_A.Process();
}
private void ProcessorA_A_UpdateProgress(object sender, UpdateProgressEventArgs e) {
OnUpdateProgress(e);
}
}
public class ProcessorB : Processor {
public void Process() {
for (int i = 0; i <= 100; i++) {
var args = new UpdateProgressEventArgs() { Caller = nameof(ProcessorB), Percentage = i, UpdateDateTime = DateTime.Now};
//Do some work
Thread.Sleep(r.Next(50,250));
OnUpdateProgress(args);
}
}
}
public class ProcessorC : Processor {
public void Process() {
for (int i = 0; i <= 100; i++) {
var args = new UpdateProgressEventArgs() { Caller = nameof(ProcessorC), Percentage = i, UpdateDateTime = DateTime.Now };
//Do some work
Thread.Sleep(r.Next(50, 250));
OnUpdateProgress(args);
}
}
}
public class ProcessorD : Processor {
public void Process() {
for (int i = 0; i <= 100; i++) {
var args = new UpdateProgressEventArgs() { Caller = nameof(ProcessorD), Percentage = i, UpdateDateTime = DateTime.Now };
//Do some work
Thread.Sleep(r.Next(50, 250));
OnUpdateProgress(args);
}
}
}
public class ProcessorA_A : Processor {
public void Process() {
for (int i = 0; i <= 100; i++) {
var args = new UpdateProgressEventArgs() { Caller = nameof(ProcessorA_A), Percentage = i, UpdateDateTime = DateTime.Now };
//Do some work
Thread.Sleep(r.Next(50, 250));
OnUpdateProgress(args);
}
}
}
public class Processor : IProcessor {
protected Random r = new Random();
public event EventHandler<UpdateProgressEventArgs> UpdateProgress;
protected virtual void OnUpdateProgress(UpdateProgressEventArgs e) {
UpdateProgress?.Invoke(this, e);
}
}
public interface IProcessor {
event EventHandler<UpdateProgressEventArgs> UpdateProgress;
}
public class UpdateProgressEventArgs {
public int Percentage { get; set; }
public string Caller { get; set; }
public DateTime UpdateDateTime { get; set; }
}
Just sending the progress from child to parent won't do the trick obviously. I hope someone can help me find a solution for this. Or if someone has another brilliant solution :)
Thanks in advance
Engine could maintain a private list of "the last completeness" of each process. In a Dictionary more than likely.
if we extend your Engine class to have this.
private Dictionary<IProcessor, int> _lastReportedPercentage = new Dictionary<IProcessor, int>();
and in the constructor where all your child processors are defined, set them all to 0.
public Engine()
{
//your other stuff
_lastReportedPercentage[_processorA] = 0;
_lastReportedPercentage[_processorB] = 0;
_lastReportedPercentage[_processorC] = 0;
_lastReportedPercentage[_processorD] = 0;
}
in your Event handler for the child processes do something like this:
private void ProcessorA_UpdateProgress(object sender, UpdateProgressEventArgs e)
{
_lastReportedPercentage[(IProcessor)sender] = e.Percentage;
var totalCompleteness = (int)Math.Floor(_lastReportedPercentage.Values.Sum() / _lastReportedPercentages.Values.Count);
OnUpdateProgress(new UpdateProgressEventArgs() { Caller = nameof(Engine), Percentage = totalCompleteness, UpdateDateTime = DateTime.Now });
}
You will then be reporting, from your Engine, the total completeness of all tasks.
There are some obvious design flaws to this, but you get the idea. It can be extended for a variable number of Processors if they're loaded from not-the-constructor, etc. but this should give you the desired output you'd want.
I would suggest having each processor keep a count of how many items it has completed, and how many items it has remaining.
This way the engine receives updates whenever an item is completed, as well as when an item is added to the processor.
As in Skintkingle's answer, you would then store the last received update from each processor within the engine.
You can then let the engine decide on the best way to put this information across. Something as simple as total completed / total remaining would work well.
I have issue (I think) with derived class. When I add some points to my list in Form 1, I can see count and iterate through listA, and it seems its okay. I have below code:
/* Add points to lists */
class A {
private Point _singlePoint;
protected List<Point> _listA = new List<Point>();
protected List<Point> _listB = new List<Point>();
//properties
public List<Point> listA {
get { return _listA; }
set { _listA = value; }
}
public Point singlePoint {
get { return _singlePoint; }
set { _singlePoint = value; }
}
public virtual void addToListA(Point a) { }
}
class B : A {
public override void addToListA(Point a) {
_listA.Add(a);
}
}
public partial class Form1 : Form {
A _myPoints = new B();
private void drawPoint()
{
for (int i = 0; i < int.Parse(txtBoxPointsCount.Text); i++)
{
_myPoints.singlePoint = new Point(rnd.Next(100, 300), rnd.Next(100, 300));
_myPoints.addToListA(_myPoints.singlePoint);
}
foreach(Point p in _myPoints.listA)
{
graph.FillEllipse(new SolidBrush(cPoint), p.X, p.Y, 6, 6);
}
}
}
In other class I want to do some math on points, but I got ArgumentOutOfRangeException
class D {
A _myPoints = new B();
public void calulations(int iterations) {
randomPoint = rnd.Next(0, _myPoints.listA.Count);
System.Windows.Forms.MessageBox.Show(_myPoints.listA.Count.ToString());
try {
for (int i = 0; i < _iterations; i++) {
//here some math
}
}
catch(ArgumentOutOfRangeException e) {
// here I got errors about no items in my list
}
} }
In class D, in MsgBox I got count = 0. Maybe I wrote classes in wrong way? Method drawPoint() is called before calculations().
Could you help? Thanks in advance :)
That is because you are operating two completely different objects,
You have created an object here
public partial class Form1 : Form
{
A _myPoints = new B();
and then in class D created another
class D
{
A _myPoints = new B();
So you are adding point to your first object and trying to access in other object.
I am having a problem return a list so that i would be able to save it in a file and then load it so that the weights are saved and be retrieved another time. Sorry for the stupid question but how can i call and save the weights List from the SaveNetwork method , i cant grasp really what i can do to solve the problem. I know that i havent created a new instance of List weights however if i do that i will loose the current weights which are stored in this list.
public class Neuron
{
private double bias; // Bias value.
private double error; // Sum of error.
private double input; // Sum of inputs.
private double gradient = 5; // Steepness of sigmoid curve.
private double learnRate = 0.01; // Learning rate.
private double output = double.MinValue; // Preset value of neuron.
public List<Weight> weights; // Collection of weights to inputs.
public Neuron() { }
public Neuron(Layer inputs, Random rnd)
{
weights = new List<Weight>();
foreach (Neuron input in inputs)
{
Weight w = new Weight();
w.Input = input;
w.Value = rnd.NextDouble() * 2 - 1;
weights.Add(w);
}
}
public static void SaveNetwork(string path)
{
FileStream FS = new FileStream(path, FileMode.Create);
BinaryFormatter BF = new BinaryFormatter();
BF.Serialize(FS,/* The List in this case is List weights ***/ );
FS.Close();
}
public void LoadNetwork(string path)
{
FileStream FS = new FileStream(path, FileMode.Open);
BinaryFormatter BF = new BinaryFormatter();
weights = (List<Weight>)BF.Deserialize(FS);
FS.Close();
}
Update for this--I am using a similar hierarchical structure as the code below which was taken from Dynamic Notions blog which explains how to create a Neural Network. What i want to achieve is that after that the Neural Network has learnt i want to be able to save the List weights so that i would be able to load the weights if the program is stopped in order to skip the training of the network. So basically from the class network i want to access this list which is in Neural Class without creating a new instance in a new method else i will only get an empty List. Hope that its clearer coz i didnt know how to explain it better... Many thanks
public class Network{
//some variables..
[STAThread]
static void Main()
{
new Network();
}
public Network()
{
LoadPatterns();
Initialise();
Train();
Test();
}
private void Train()
{
double error;
do
{
error = 0;
foreach (Pattern pattern in _patterns)
{
double delta = pattern.Output - Activate(pattern);
AdjustWeights(delta);
error += Math.Pow(delta, 2);
}
Console.WriteLine("Iteration {0}\tError {1:0.000}", _iteration, error);
_iteration++;
if (_iteration > _restartAfter) Initialise();
} while (error > 0.1);
}
private void Test()
{
}
// Must be able to call and save the List<Weight> From here
private double Activate(Pattern pattern)
{
}
private void AdjustWeights(double delta)
{
_output.AdjustWeights(delta);
foreach (Neuron neuron in _hidden)
{
neuron.AdjustWeights(_output.ErrorFeedback(neuron));
}
}
private void Initialise()
{
_inputs = new Layer(_inputDims);
_hidden = new Layer(_hiddenDims, _inputs, _rnd);
_output = new Neuron(_hidden, _rnd);
_iteration = 0;
Console.WriteLine("Network Initialised");
}
private void LoadPatterns()
{
}
}
public class Layer : List<Neuron>
{
public Layer(int size)
{
for (int i = 0; i < size; i++)
base.Add(new Neuron());
}
public Layer(int size, Layer layer, Random rnd)
{
for (int i = 0; i < size; i++)
base.Add(new Neuron(layer, rnd)); //this is where Neuron class is instantiated
}
}
public class Neuron
{
//some other vars
private List<Weight> _weights; // This is the list in question.
public Neuron() { }
public Neuron(Layer inputs, Random rnd)
{
_weights = new List<Weight>();
foreach (Neuron input in inputs)
{
Weight w = new Weight();
w.Input = input;
w.Value = rnd.NextDouble() * 2 - 1;
_weights.Add(w);
}
}
}
public class Weight
{
public Neuron Input;
public double Value;
}
Remove the static keyword from SaveNetwork() and use weights where you have your comment.