I'm using ETW, and logging some events that have stop & stop opcodes, e.g.
[Event(1, Task = Tasks.ActivateTask, Opcode = EventOpcode.Start)]
public void ActivateTaskStart(string TaskName)
{
if (IsEnabled())
{
WriteEvent(1, TaskName);
}
}
[Event(2, Task = Tasks.ActivateTask, Opcode = EventOpcode.Stop)]
public void ActivateTaskStop(string TaskName)
{
if (IsEnabled())
{
WriteEvent(2, TaskName);
}
}
If I have two threads that are both logging ActivateTask start/stop events, how do I make sure the events are correctly paired up? e.g. If I have:
Thead-A: ActivateTaskStart
Thead-B: ActivateTaskStart
then later
Thead-A: ActivateTaskStop
Thead-B: ActivateTaskStop
from my reading of the ETW docs, it will default to assuming that the Stop event belongs to the most recent, unpaired, Start event - but I want to make sure I'm linking the correct Start/Stop events.
Is that possible? If so, how?
To make this more complicated, there's a chance that the Start and Stop events might be coming from different threads (if I need to, I should be able to make the threads sticky).
This is called ActivityTrackig and works since .Net 4.6. To get this working automatically, you can't use own Thread implementations, you have to wrap all calls into System.Threading.Tasks.Task calls.
Related
I've read about VB6's threading model, and found this link very helpful.
With the following points in mind...
Do VB6 event handlers run in separate threads?
Not really, because there aren't separate threads. Your code runs on a single thread, wrapped in the service-like architecture I described above. Most of what you talk to that is threaded is other COM objects which have their own apartments. So to communicate back and forth, you are basically doing RPC calls when the threads talk to each other: you aren't directly manipulating them.
Among other things, the VB6 program had a timer that woke up every 4 seconds, manipulated some global variables and went back to sleep, while the main program was doing its thing. I can't understand why this didn't result in collisions.
The "timer" is on a separate thread created for the timer, but when it calls into your code, you are guaranteed not to interrupt any other functions, because the function calls are basically queued one at a time in the thread.
... I've attempted to implement VB6's event handling behavior in the code below.
ActionManager.cs
public class ActionManager : IDisposable
{
private readonly BlockingCollection<Action> ActionQueue = new BlockingCollection<Action>(new ConcurrentQueue<Action>());
public ActionManager()
{
}
public void Kickoff()
{
// Start consumer thread
new Thread(ExecuteLoop)
{
IsBackground = true
}.Start();
}
public void AddAction(Action action)
{
ActionQueue.Add(action);
}
private void ExecuteLoop()
{
// Blocks until new actions are available
foreach (var action in ActionQueue.GetConsumingEnumerable())
{
action.Invoke();
}
}
public void Dispose()
{
ActionQueue.CompleteAdding();
ActionQueue.Dispose();
}
}
MainForm.cs
public partial class MainForm : Form
{
public ActionManager actionManager = new ActionManager();
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load()
{
// Perform preparatory steps, such as initializing resources,
// configuring settings, etc.
// (Insert preparatory steps here)
// Once preparatory steps are complete, start the ActionManager
actionManager.Kickoff();
}
// Event handler for when the Timer's specified interval has elapsed
private void Timer_Tick(object sender, EventArgs e)
{
actionManager.AddAction(() => {
// (Insert timer event steps here)
});
}
// Event handler for when SomeButton is clicked
private void SomeButton_Click(object sender, EventArgs e)
{
actionManager.AddAction(() => {
// (Insert button click event steps here)
});
}
}
An ActionManager manages an event queue by executing each event one after the other. Any type of event, such as mouse clicks, timer ticks, network packet arrivals, and the like, will enqueue their respective event handling code to the event queue. This way, the code will run "on a single thread," which will also handle the problem of unsynchronized global variables.
Is this a correct implementation? Please share your thoughts!
What you have is a somewhat decent starting place for a custom message loop, if you were to begin writing your own UI framework from scratch. But you're using winforms, you're not writing your own UI framework from scratch. Winforms already has its own message loop that processes messages, and a mechanism for scheduling work to run in that loop. You don't need to create any of that from scratch. All of the events fired from the winforms controls will already be firing in the UI thread, so you don't need to create your own special UI thread and manage scheduling actions into it.
In fact doing so would cause problems, as you would end up having the UI thread that winforms is using to manage its UI objects, and you would have your second thread that you're creating. If you ever used any UI controls in that thread things would break as they are designed to only be used from the winforms UI thread.
(I figured I should ask in the comments first if my suspicion about a legacy app was right.)
Okay, time for the bad news: you should NOT do this. Please, please, please, do NOT do this. I'm telling you as a developer that has been in your shoes that this will NOT end well if you try to go down this road.
Here's what's going on. You've got a legacy app - and it probably does a lot of things that are very important for the company.
But the problem is, it's likely not written very well, it's cranky, and it did not port very well into the modern .NET world.
Now, you can try to go down the road of shoehorning .NET into the VB6 model of the world... but all you've done is kick the can down the road. You've still got a badly-written, cranky legacy app that you're still having to maintain - and worse, you're having to maintain the .NET-to-VB6-threading-approach as well.
I can guarantee you that the correct approach is to Redesign/Rearchitect it. Write out what it does, ask yourself if there's anything you can do to improve the process, and write it from scratch in .NET. Several reasons:
You're going to have a more stable end product
You're going to spend FAR less time maintaining the new product
You'd have to rearchitect the program eventually anyways.
If it helps, let me tell you a story of an old job I had. A coworker and I were both responsible for porting VB6 apps into .NET. He had a tire inspection app, and I had a rubber mixing app.
He tried porting his existing VB6 app into .NET, getting all the language
differences worked out, GUI/Thread issues altered, etc
I sat down with a rep from the user area, and went ahead just
rewriting the rubber mixing app.
... I was done much sooner than the coworker, my app was far more user-friendly, and it was a heck of a lot less of a maintenance issue.
Management likely will not like hearing advice that you should rewrite the whole thing. But you need to push and fight for this. If it helps, point out that most software dev time isn't on new coding, it's on maintaining existing software. It might take more time up front to get it rewritten (even that's not a given) but it'll pay for itself very quickly in the long run.
I have a piece of code that does some calculations and then calls the form.show command. Now I have a library (the revit api) that does not allow me to store variables in a project without being in the main thread.
The logical solution for this is to get the spawned thread to call the main thread using say a producer/consumer pattern with code looking a bit like this:
form.Show(owner);
while(AppIsRunning){
if(clicked)
commit();
else
Thread.sleep(100);
}
However when I do this the gui does not load fully (black background, no text in buttons ext.).
I have also tried doing this using the evoke method
private void BtnOK_Click(object sender, System.EventArgs e)
{
Commit();
Invoke(Commit);
}
private void Invoke(Action commit)
{
commit.Invoke();
}
However this just tells me that it's not the main thread that's executing the commit function.
Is there another way to do this or am I just making an error.
Just to be clear I have a form.show(owner) command that throws an error if it's not executed by the main thread. I also have a commit() function that must be excused by the main thread or it throws an error. The execution must wait until a button press. But the main thread polling the gui thread for changing causes the program to hang. According to my google search it' s also possible to do something involving an external event to get back into the right context but the example given was using python to invoke c# code, is there a good way to raise an external event to get back into a given thread in c#?
Edit: based on some suggestions I have created the following code:
public class ThreadManager
{
static List<ThreadAble> orders = new List<ThreadAble>();
public static bool running = false;
public static void execute(ThreadAble action)
{
orders.Add(action);
}
static System.Timers.Timer timer;
public static void RegisterAPIThreadAndHold(ExternalCommandData commandData)
{
UIApplication uiapp = commandData.Application;
uiapp.Idling += Application_Idle;
}
private static void Application_Idle(Object o,IdlingEventArgs e)
{
if (orders.Count != 0)
{
ThreadAble f = orders.First();
orders.Remove(f);
f.execute();
}
}
}
public interface ThreadAble {
void execute();
}
However this does not appear to actually run when I use it as
public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
Form frm = new OverviewForm(ExternalCommandData commandData);
frm.show()
ThreadManager.RegisterAPIThreadAndHold(commandData);
ThreadManager.Execute(new run_ThrowError())
where ThrowError.execute() is
Throw new Exception(" this is actually being executed" );
Your first example could work if you will replace Thread.Sleep by the System.Windows.Forms.Application.DoEvents(). It should give time to paint GUI and do not froze application completly.
form.Show(owner);
while(AppIsRunning){
if(clicked)
commit();
else
{
System.Windows.Forms.Application.DoEvents();
// Thread.sleep(100);
}
}
But this is not perfect solution to achieve this.
Better would be calling Dispatcher.Invoke command inside your dialog to perform MainThread operations.
You can use i.e. GalaSoft library - please refer to DispatcherHelper object documentation and samples.
The two ways to do this I'm aware of are with the External Event or the Idling event.
With the idling event, you'll register it, and while it is registered, your code (in the main thread) will get a callback from Revit every time that it's not busy with something else. Often a few times per second.
Once you are in the Idling callback, then you're able to create transactions and interact with the model. So your callback checks the state of the form and decides whether there is something to do.
The External Event works similarly in terms of registration, but you're able to request a trigger of the callback.
Jeremy Tammik must have 20 posts on thebuildingcoder.typepad.com on Modeless dialog / Revit stuff.
For a simple solution to this, please refer to the Revit SDK ModelessDialog ModelessForm_ExternalEvent sample application. It demonstrates exactly what you are asking for.
Edit: For clarification, this is in Unity, and is tied to Update(). So the events will be triggered once per frame for any number of frames. Both events can be triggered independently by the user, but there is an overlap in which both can be triggered. In this case I only want one of the two methods that will be called by the two events to actually run.
I'm trying to make a method that is called by one event and other method that is called by a 2nd event be linked in a way that only one of those two methods can be called or ran at the same time.
The events are triggered by an action of the user, both events can be triggered at the same time. But I only want one of the two methods that would be called to actually run if both events are triggered.
I was thinking something along the like of the following example, obviously the example may not be accurate, but the gist of what I am trying to accomplish is there.
Pseudo Code Example:
public delegate void OneHandler();
public event OneHandler OneEvent;
private void One()
{
if(some requirement && TEvent != null)
{
TEvent();
}
}
public delegate void TwoHandler();
public event TwoHandler TwoEvent;
private void Two()
{
if(some requirement && TEvent != null)
{
TEvent();
}
}
SomeClass.OneEvent += ActionOne();
SomeClass.TwoEvent += ActionTwo();
private void ActionOne()
{
if(TwoEvent is not firing)
{
Do Something;
}
}
private void ActionTwo()
{
if(OneEvent is not firing)
{
Do Something;
}
}
A crude diagram. The tan area moves down/left, the green areas move diagonally. I essentially want the tan area which have their own events, to not run their methods if the mouse is within that entire area.
Events fire one at a time, not all at once. Even if the same user action was going to cause both events to fire one after the other, there is no way to know that both events will fire, or in what order they will fire.
To be more clear: I didn't mean events can never be fired concurrently. I mean that, in general, there is no piece of code that determines, for a particular situation, the complete set of events which will be fired. You can't tell ahead of time which will fire, or in which order, or even on which threads.
For example, a particular user interface action (or user gesture) might cause several events to fire. In general, you can't depend on the number of events to be fired, or the order in which they will be fired.
There are some situations, like in ASP.NET web forms, where you can be assured that if the user clicks a button which has a Click event handler, that the page Load event will fire and then that the button Click event will fire. But this is because this behavior is defined and documented that way. If the order changed, or if, for instance, the page Load event stopped firing, then this would break a large number of ASP.NET web forms applications.
If all you're trying to do is guarantee that concurrent triggering (like two threads running on different cores) will never be allowed, you'll want to use something like a mutex. You would have both handlers perform a WaitOne(0) to see if the other handler is working, returning immediately if the call returns false (since the other method must be executing) then in a guaranteed-execution block (such as a finally) you would release the mutex.
How about use bool variable as flag ?
private bool flag[2] = [false, false];
private void ActionOne()
{
flag[0] = true;
if(!(flag[0])&&flag[1]))
{
Do Something;
}
flag[0] = false;
}
private void ActionTwo()
{
flag[1] = true;
if(!(flag[0] && flag[1]))
{
Do Something;
}
flag[1] = false;
}
We want to display a "Loading, please wait..." screen before the application starts executing other functions on a Win CE 5.0 powered device. The application is being developed using .NET Compact Framework 3.5 (C#).
The issue is that, the UI is only updated once the set of current processes are completed, to a stage where other functions will only run with user interaction. C# has a Form.Shown() event, which would allow the application to run other functions, only ONCE the form has been displayed. However, the Compact-Framework does NOT include.
The solution I've approached was using multi-threading, where I would have one thread which would display the "Loading, please wait..." screen, and the other would take care of other function.
The issue with Threading is, when managing UI components, it gives an error if not applied the correct techniques:
public Form1()
{
InitializeComponent();
ThreadStart tstart = new ThreadStart(showLoad);
Thread t1 = new Thread(tstart);
Thread t2 = new Thread(checkConnect);
t1.Start();
t2.Start();
}
private void checkConnect()
{
conn.portConnect(); //Connects to port Successfully
if (conn.isConnected == true) //Variable which checks the connectivity status
{
panelMENUshow();
}
else
{
panelCONFIGshow();
}
}
private void showLoad()
{
if (imgLoading.InvokeRequired)
{
imgLoading.Invoke((Action)(() => imgLoading.Show())); //Image box displaying "Loading, please wait..." shows successfully if I use Control.Invoke
}
//If I don't use Control.Invoke I get the following error:
//"Control.Invoke must be used to interact with controls created on a separate thread."
}
On the showLoad() function, it is not a problem to add Control.Invoke. However, the functions panelMENUshow() and panelCONFIGshow() contains many bits of code that manages UI components, and it would be not practical to use Control.Invoke in every line of code referring to a UI component.
Is there a way of:
stopping the threading but carry on running the code that involves UI management?
practically manage UI components within a thread?
PS: The approach was based on the answer of this post.
Use the refresh function to force the control to be immediately redrawn.
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.refresh(v=vs.90).aspx
When writing WinForm apps you want to keep the complexities of threading away from the main UI thread. I've seen too many applications with thread code weaving in and out of them, tying the logic into a knot.
Instead, model anything that requires any kind of threading as a component that, while it may use threads internally, presents a friendly, even-based model to the outside world. These components should not have any direct interaction with your UI.
Given that, your code would look something more like this (just an example, not syntax checked and probably with lots of typos etc, but it will give you an idea):
public class CommunicationObject
{
// you will probably have several EventArgs to define to pass extra info
public event EventHandler<EventArgs> Connected;
// you need this instance to dispatch events to the UI thread
private Control _invoker;
public CommunicationObject(Control invoker)
{
_invoker = invoker;
// start a thread here, or better yet, add an Enabled property or
// Start method to kick it off
}
// from the thread that is doing the real work, call this when you are connected
private void OnConnected()
{
_invoker.Invoke(() =>
{
EventHandler<EventArgs> handler = Connected;
if (handler != null)
{
handler(this, EventArgs.Empty); // eventually you might need your own event args
}
});
}
}
public class Form1 : Form
{
private CommunicationObject _comm;
public Form1()
{
InitializeComponent();
imgLoading.Show(); // show msg until connected
_comm = new CommunicationObject(this);
_comm.Connected += Comm_Connected; // wire up event handler
}
private void Comm_Connected(object src, EventArgs e)
{
if (imgLoading.Visible)
{
imgLoading.Hide(); // hide once connected
}
panelMENUshow();
}
}
Note that the form has no threads in it at all. Push that complexity into stand-alone objects. It might seem like a bit more work, but you will thank yourself later!
Generally with services, the task you want to complete is repeated, maybe in a loop or maybe a trigger or maybe something else.
I'm using Topshelf to complete a repeated task for me, specifically I'm using the Shelf'ing functionality.
The problem I'm having is how to handle the looping of the task.
When boot strapping the service in Topshelf, you pass it a class (in this case ScheduleQueueService) and indicate which is its Start method and it's Stop method:
Example:
public class QueueBootstrapper : Bootstrapper<ScheduledQueueService>
{
public void InitializeHostedService(IServiceConfigurator<ScheduledQueueService> cfg)
{
cfg.HowToBuildService(n => new ScheduledQueueService());
cfg.SetServiceName("ScheduledQueueHandler");
cfg.WhenStarted(s => s.StartService());
cfg.WhenStopped(s => s.StopService());
}
}
But in my StartService() method I am using a while loop to repeat the task I'm running, but when I attempt to stop the service through Windows services it fails to stop and I suspect its because the StartService() method never ended when it was originally called.
Example:
public class ScheduledQueueService
{
bool QueueRunning;
public ScheduledQueueService()
{
QueueRunning = false;
}
public void StartService()
{
QueueRunning = true;
while(QueueRunning){
//do some work
}
}
public void StopService()
{
QueueRunning = false;
}
}
what is a better way of doing this?
I've considered using the .NET System.Threading.Tasks to run the work in and then maybe closing the thread on StopService()
Maybe using Quartz to repeat the task and then remove it.
Thoughts?
Generally, how I would handle this is have a Timer event, that fires off a few moments after StartService() is called. At the end of the event, I would check for a stop flag (set in StopService()), if the flag (e.g. your QueueRunning) isn't there, then I would register a single event on the Timer to happen again in a few moments.
We do something pretty similar in Topshelf itself, when polling the file system: https://github.com/Topshelf/Topshelf/blob/v2_master/src/Topshelf/FileSystem/PollingFileSystemEventProducer.cs#L80
Now that uses the internal scheduler type instead of a Timer object, but generally it's the same thing. The fiber is basically which thread to process the event on.
If you have future questions, you are also welcomed to join the Topshelf mailing list. We try to be pretty responsive on there. http://groups.google.com/group/topshelf-discuss
I was working on some similar code today I stumbled on https://stackoverflow.com/a/2033431/981 by accident and its been working like a charm for me.
I don't know about Topshelf specifically but when writing a standard windows service you want the start and stop events to complete as quickly as possible. If the start thread takes too long windows assumes that it has failed to start up, for example.
To get around this I generally use a System.Timers.Timer. This is set to call a startup method just once with a very short interval (so it runs almost immediately). This then does the bulk of the work.
In your case this could be your method that is looping. Then at the start of each loop check a global shutdown variable - if its true you quit the loop and then the program can stop.
You may need a bit more (or maybe even less) complexity than this depending on where exactly the error is but the general principle should be fine I hope.
Once again though I will disclaim that this knowledge is not based on topshelf, jsut general service development.