I started a small app (C#, .Net4, console app) and it was a basic idea for moving files around at home based on rules.
This app has grown and become extremely useful. So my task is to break it into more reusable classes and smaller projects (class libraries).
I have a generic 'Show' function that accepts a string, and a error_level id. Based on that, I would output text to my console window in a certain colour. All is fine when it's all in one big class, but I want to move a method to it's own class libabry - however, I want it to report updates while it's processing, to my UI (Console window, for now). When I move it to the class, obviously, class to my 'Show' method', break.
Is there a way I can get messages sent from my class method, back to my UI? It's messages like, 'Opened Config file', 'Processing 12 new files', 'Success'.
And as it happens, the UI gets the messages and displays them, while the method finishes it's job.
At the moment, it's a Console App project. My plan is to rip out the working code, keeping the console app for testing, and later, change the 'UI' into a nice WPF desktop application. (I'm trying to learn WPF, and decided to use a small project I started ages ago, and 'skin it').
I would suggest that you add an interface, implement that interface in your UI, and pass a reference to the class that implements the interface to your new classes.
This approach should work if you are performing the work in a single thread or multiple threads.
For example, the interface:
public interface INotify
{
void Notify(string Msg);
}
the UI:
public class Form1 : INotify
{
// This is the method where you instantiate the new worker process
public void DoSomeWork() {
NewClass Worker = New NewClass(this);
}
public delegate void NotifyDelegate(string Msg);
public void Notify(string Msg)
{
txtLog.Text += Msg + Environment.NewLine;
}
void INotify.Notify(string Msg)
{
this.INotify_Notify(Msg);
}
private void INotify_Notify(string Msg)
{
if (this.InvokeRequired)
{
this.Invoke(new NotifyDelegate(Notify), Msg);
}
else
{
this.Notify(Msg);
}
}
}
and the new class (just call notify in this class to send the message):
public class NewClass
{
private INotify m_Notifier;
private void Notify(string Msg)
{
m_Notifier.Notify(Msg);
}
public NewClass(INotify oNotifier)
{
m_Notifier = oNotifier;
}
}
Update with alternate implementation
An alternate implementation, which will work with static classes, is to implement a delegate.
For example, here is the delegate:
public delegate void NotifyDelegate(string Msg);
Here is the sample static class for the console app:
static class Program
{
private static NotifyDelegate m_Notifier;
static void Main(string[] args)
{
m_Notifier = new NotifyDelegate(Notify);
NewClass oNewClass = new NewClass(m_Notifier);
// Your work code here
}
static void Notify(string Msg)
{
Console.WriteLine(Msg);
}
}
and a revised version of the work class:
public class NewClass
{
private NotifyDelegate m_Notifier;
public void Notify(string Msg)
{
m_Notifier.Invoke(Msg);
}
public NewClass(NotifyDelegate oNotifier)
{
m_Notifier = oNotifier;
}
}
If i understand your question correctly i would implement event handling so that your UI can subscribe to some sort of status event.
An alternative would be to use some kind of Logging Framework like NLog and log to a static method in your UI via the methodCall target.
Since you are using WPF it would make sense to use MVVM. This would probably be the best way to create powerful and maintainable UIs.
Well this is usually done with Binding, you bind your viewModel with the view, and any changes to the viewModel, will be directly displayed in your UI.
Could the class/es that do work raise an event that the class on the UI thread is listening to? The 'worker' class would raise an event with some parameters, the listener class would then write that information to the UI.
Related
Is there a way to call a method to be executed before another method, like a trigger?
Something like an attribute that indicates the method to be executed, like this:
[OnBefore(MethodToBeExecutedBefore)]
public void MethodExecutedNormally()
{
//method code
}
I have a situation that I need to call a check method very often, and most of the time, they are before methods that take too long to execute.
There is no built in way to achieve this result, if you are using a dependency injection mechanism you can use the interception facilities if the DI framework supports this. (Ex: Unity, NInject)
If you want to go low level you can also use Reflection.Emit to create a derived class at runtime, that overrides methods with a particular attribute that invokes any extra functionality you want, but that is more difficult.
What you are talking about is called AOP or Aspect Oriented Programming.
There are no built-in options in C#. While Attributes exists, there is no mechanism to take any actions with them. You always need a piece of code that reads those attributes and then does something. Attributes themselves are only metadata and markers.
As far as external tools go, Postsharp is the de-facto standard AOP postcompiler for .NET, but it's not free (at least not for real use, there is a free version you may want to try, maybe it's enough for your use-case).
I think you should consider an event driven approach.
You could create an interface and some base classes to handle the event, then have your long running classes inherit from it. Subscribe to the event and handle accordingly:
public delegate void BeforeMethodExecutionHandler<TArgs>(ILongRunningWithEvents<TArgs> sender, TArgs args, string caller);
public interface ILongRunningWithEvents<TArgs>
{
event BeforeMethodExecutionHandler<TArgs> OnBeforeMethodExecution;
}
public class LongRunningClass<TArgs> : ILongRunningWithEvents<TArgs>
{
private BeforeMethodExecutionHandler<TArgs> _onBeforeMethodExecution;
public event BeforeMethodExecutionHandler<TArgs> OnBeforeMethodExecution
{
add { _onBeforeMethodExecution += value; }
remove { _onBeforeMethodExecution -= value; }
}
protected void RaiseOnBeforeMethodExecution(TArgs e, [CallerMemberName] string caller = null)
{
_onBeforeMethodExecution?.Invoke(this, e, caller);
}
}
public class ConcreteRunningClass : LongRunningClass<SampleArgs>
{
public void SomeLongRunningMethod()
{
RaiseOnBeforeMethodExecution(new SampleArgs("Starting!"));
//Code for the method here
}
}
public class SampleArgs
{
public SampleArgs(string message)
{
Message = message;
}
public string Message { get; private set; }
}
Sample usage:
public static void TestLongRunning()
{
ConcreteRunningClass concrete = new ConcreteRunningClass();
concrete.OnBeforeMethodExecution += Concrete_OnBeforeMethodExecution;
concrete.SomeLongRunningMethod();
}
private static void Concrete_OnBeforeMethodExecution(ILongRunningWithEvents<SampleArgs> sender, SampleArgs args, string caller)
{
Console.WriteLine("{0}: {1}", caller ?? "unknown", args.Message);
}
The message SomeLongRunningMethod: Starting! will be output before the long-running method executes.
You could add the caller name to the args. I whipped this out real quick to illustrate.
UPDATE: I see you added tags for ASP.NET MVC. The concept still applies to controllers as controllers are just classes.
I do not understand some things of work with callbacks.
I have some third-party code wich connect,disconnect,subscribe to values from some system.
So, the example is:
class Subscriber:ISubscriber
{
public void OnConnected()
{
}
public void OnDisconnected()
{
}
}
Then, it uses:
var subscriber=new Subscriber();
_someSystemObj.CreateConnection(subscriber); //i do not understand how it works there
And then _someSystemObj calls OnConnected or OnDisconnected.
So, i have two questions:
1.How can _someSystemObj calls OnConnected method (it use Observer pattern or may be it use it other way. Can you describe it? Get some schematic code to understand how it may work.
If i want to do many steps when OnDisconnect happens: should i throw some public event to other classes? I mean than i can not do Disconnection in this OnDisconnect method (i have to do some steps in other part of my code and at old version of this API i just rethrow event OnDisconnect on top of my program and then handle it.)
This old version of code looks like:
_server.OnDisconnect+=OnDisconnectHandler;
void OnDisconnectHandler(..)
{
if(OnReconnect!=null)//some public event
OnReconnect(e);// throw on top of my program and then handle it there
}
At new version of API i try to solve it by add public event and when OnDisconnect happens throw it on top:
class Subscriber:ISubscriber
{
public event EventHandler<EventArgs> OnDisconnectedHappens;
public void OnConnected()
{
}
public void OnDisconnected()
{
if(OnDisconnectedHappens!=null)
OnDisconnectedHappens(this,e);//thow on top
}
}
And in some place:
_subscriber.OnDisconnectHappens+=OnDisconnectHandler; //and do my work
Or, may be it not right way. May be i should do something else?
Please,can you give me a some link, that i can learn about this model of event callbacks?
Or, may be i do it correctly?
How can _someSystemObj call OnConnected method?
Well, you gave it a subscriber when you called CreateConnection(subscriber). It's probably implemented something like this:
private readonly List<ISubscriber> _subscribers = new List<ISubscriber>();
public void CreateConnection(ISubscriber subscriber)
{
_subscribers.Add(subscriber);
}
private void OnConnectedNotifySubscribers()
{
foreach (ISubscriber subscriber in _subscribers)
{
subscriber.OnConnected();
}
}
If I want to do many steps when OnDisconnect happens, should I raise some public event to other classes?
That is a valid option, but it can get difficult to debug when there are too many layers in an event chain. Another option is to increase the capability of your Subscriber class so that it can do everything necessary to handle the subscription events.
class EmpoweredSubscriber : ISubscriber
{
private readonly DisconnectWorker _worker;
private readonly DisconnectHelper _helper;
public EmpoweredSubscriber(DisconnectWorker worker, DisconnectHelper helper)
{
_worker = worker;
_helper = helper;
}
public void OnConnected()
{
}
public void OnDisconnected()
{
_worker.DoWork();
_helper.DoHelp();
// more...
}
}
I have a project and am right now at a point, where it's growing complexity forces me to think about it's structure. To explain it in a few sentences:
I have a main application as UI. It allows the user to run different tests and should display status updates and results.
I have a whole bunch of classes containing different tests on some hardware. All those classes implement an iTest interface to ensure compatibility.
Where I am right now: I want to have status updates (which I don't get right now). I need some kind of StatusUpdate-Event fired in the Test-Classes and receive those events in my UI. I'm new to delegates and event handlers so I have no clue which way is the best to choose for this. Following the answer from here "How to add an event to a class" means I'd have to add a event handler each time I instantiate one of my test classes. That would generate a whole load of redundant code that I think is unnecessary.
I'd like to have one function in my UI named sth. like "StatusUpdateEventHandler(string textToDisplay)". It should not matter, which Test-Class invokes this event.
Can anyone give me some direction where to go at? Thank's a lot :)
I'll use a base class that have common properties/methods/events to report progress back to the UI. Quickly, this is how I would approach the problem:
Create an event Handler to report progress:
public delegate void StatusChangedEventHandler(object sender, StatusChangedEventArgs e);
Create an abstract base class:
public abstract class TestBase:ITest
{
// An event that clients can use to be notified whenever the
// elements of the list change.
public event StatusChangedEventHandler StatusChanged;
protected virtual void OnStatusChanged(StatusChangedEventArgs e)
{
if (StatusChanged != null)
StatusChanged(this, e);
}
protected virtual void ReportProgress (int percentage, string step)
{
OnStatusChanged(new StatusChangedEventArgs()
{
Percentage = percentage,
Step = step
});
}
public abstract void Execute();
}
Create a EventArgs that will be used to get data from the event in your UI:
public class StatusChangedEventArgs:EventArgs
{
public int Percentage { get; set; }
public string Step { get; set; }
}
Then make sure that your tests use the base test class:
public class SimpleTest : TestBase
{
public override void Execute()
{
ReportProgress(10, "STEP 1");
ReportProgress(25, "STEP 2");
ReportProgress(55, "STEP 3");
ReportProgress(70, "STEP 4");
ReportProgress(100, "STEP 5");
}
}
Then hook up the event to your UI, here's my implementation in a console application:
class Program
{
static void Main(string[] args)
{
SimpleTest simpleTest = new SimpleTest();
simpleTest.StatusChanged += SimpleTest_StatusChanged;
simpleTest.Execute();
Console.ReadLine();
}
private static void SimpleTest_StatusChanged(object sender, StatusChangedEventArgs e)
{
Console.WriteLine($"{e.Percentage} - {e.Step}");
}
}
I couldn't say you provided a lot of info to suggest a really helpful response. :-) It seems to me you look for something like generic events, see example within the article. You'd subscribe to the events which are fired by the test units, so the relevant string is passed along with each particular event. Besides, you could consider some class hierarchy to support your test units.
Hope it brings you some fresh thoughts to find the direction.
I am working on a VS project/solution that is used by different applications. My job is to refactor the project and change it from using xxxAsync method to using BeginInvoke.
I came up to something similar to the following code:
public class AsyncTestModel {
private delegate string DoTaskDelegate();
public static EventHandler<TaskCompletedEventArgs> OnTaskCompleted;
public static void InvokeTask() {
DoTaskDelegate taskDelegate = Task;
taskDelegate.BeginInvoke(new AsyncCallback(TaskCallback), null);
}
private static string Task() {
Thread.Sleep(5000);
return "Thread Task successfully completed.";
}
private static void TaskCallback(IAsyncResult ar) {
string result = ((DoTaskDelegate)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate).EndInvoke(ar);
if (OnTaskCompleted != null) {
OnTaskCompleted(null, new TaskCompletedEventArgs(result));
}
}
}
public class TaskCompletedEventArgs : EventArgs {
private string _message;
public TaskCompletedEventArgs(string message) : base() {
_message = message;
}
public string Message {
get {
return _message;
}
}
}
I've tested this on a new UI project I've created. The UI project contains a button and a label controls. The UI has the following code:
private void button1_Click(object sender, EventArgs e) {
AsyncTestModel.OnTaskCompleted += OnTaskCompleted;
AsyncTestModel.InvokeTask();
}
private void OnTaskCompleted(object sender, TaskCompletedEventArgs e) {
UpdateLabel(e.Message);
}
private void UpdateLabel(string message) {
this.label1.Text = message;
}
After running this, I've encountered the cross-thread exception saying the the control 'label1' is being accessed from other thread aside the thread that it was created.
Is there a way for me to invoke the OnTaskCompleted event handler on the same thread that calls the BeginInvoke method? I know I could just use the form's InvokeRequired and call the form's BeginInvoke like the following:
private delegate void DoUpdateLabelDelegate(string message);
private void UpdateLabel(string message) {
if (this.InvokeRequired) {
IAsyncResult ar = this.BeginInvoke(new DoUpdateLabelDelegate(UpdateLabel), message);
this.EndInvoke(ar);
return;
}
this.label1.Text = message;
}
But the solution above will require me to ask and apply that solution to the other development team handling applications that uses my project/solution. Those other developers shouldn't be required to know that the methods hooked to the event handler are running from different thread.
Thanks, in advance.
As designed, no, you have absolutely no idea which thread is the one on which the client's UI runs.
You can arbitrarily demand that your InvokeTask() is to be called from that UI thread. Now you know, you can copy SynchronizationContext.Current in the InvokeTask() method and, later, call its Post() or Send() method to call a method that fires the event. This is the pattern used by, for example, BackgroundWorker and async/await. Do note that copying the Current property is required to make this work, don't skip it.
That of course still won't work when your InvokeTask() method is not called from the UI thread, you'll see that Synchronization.Current is null and have no hope to marshal the call. If that's a concern then you could expose a property of type ISynchronizeInvoke, call it SynchronizingObject. Now it is up to the client code to make the call, they'll have no trouble setting the property, they'll simply assign this in their form class constructor. And you use the property's Post or Send method to call the method that raises the event. This is the pattern used by for example the Process and FileSystemWatcher classes. Don't use it if you expect your library to be used by non-Winforms client apps, unfortunately later GUI libraries like WPF and Silverlight don't implement the interface. Otherwise the exact same problem with approaches like calling Control.Begin/Invoke() yourself.
try to use this, maybe it can help you.
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
//Do something...
});
I have a method that does some stuff that takes a while and posts progress/status messages back. The method used to be the Main() static method in my console Program class. Later, I decided to move the functionality into a shared library assembly, so that the same functionality could be accessed by a new web api project, so a different user interface with different mechanisms for stdio.
What is a good design pattern to replace all my Console.Writeline() calls in the moved method?
I'm thinking along the lines of adding an observable collection (of strings) to store the messages and then getting any calling assemblies to subscribe to changes on the collection and implement their own ui mechanisms for displaying messages back to the user.
Is this reasonable or is this reinventing the wheel? Is there already a purpose built method in the framework to handle a scenario like this?
Edit:
Thanks to #astef, I implemented it like so:
public interface IMessageObserver
{
void Notify(string message);
void Notify(string format, params object[] args);
}
public class ConsoleMessageObserver : IMessageObserver
{
public void Notify(string message)
{
Console.WriteLine(message);
}
public void Notify(string format, params object[] args)
{
Console.WriteLine(format, args);
}
}
class Program
{
static void Main()
{
Library.LongRunningMethod(new ConsoleMessageObserver());
}
}
static class Library
{
public static void LongRunningMethod(IMessageObserver observer)
{
observer.Notify("Some progress happened...");
}
}
If you need someone to handle your progress messages, just define it:
public interface IProgressObserver
{
void NotifyProgress(double done);
}
And use:
public void YourLongRunningMethod(IProgressObserver progressObserver)
{
// ...
progressObserver.NotifyProgress(1d);
}
Now you can be more specific on who will actually handle this messages. For example:
public class ConsoleProgressObserver : IProgressObserver
{
public void NotifyProgress(double done)
{
Console.WriteLine("Progress: {0:0.00}%", done * 100);
}
}
Here's one that was used in Windows 98 system ;)
public class StuckingProgressObserver : IProgressObserver
{
private const double stucksAfter = 0.95;
private readonly IProgressObserver wrapee;
public StuckingProgressObserver(IProgressObserver wrapee)
{
this.wrapee = wrapee;
}
public void NotifyProgress(double done)
{
if (done < stucksAfter)
{
wrapee.NotifyProgress(done);
}
}
}
Using an event, like #astef suggests is a good idea, but their code isn't idiomatic C#. .NET supports delegates directly, so there is no need for a one method interface.
In C# we'd define a class ProgressChangedEventArgs : EventArgs and then add an EventHandler<ProgressChangedEventArgs> ProgressChanged to the class that generates the event.
In fact the framework already includes those in the System.ComponentModel namespace.