I have the following locking scenario which seems to miss a lock once in a while, letting 2 code instances to run in parallel. Would appreciate your help in analyzing/fixing the code.
public delegate void _D(A a);
namespace ExternalDll {
public event _D D;
}
namespace MainSpace {
ExternalDll _externalDll;
public static object lockObj = new object();
public static int counter = 0;
.
.
_externalDll.D += new _D(myEventHandler);
.
.
void myEventHandler(A a) {
lock (lockObj) {
counter++;
// do staff, printouts, etc.
Console.WriteLine("First={0}\n", counter);
// do other staff
Console.WriteLine("Second={0}\n", counter);
}
}
}
ExternalDll is a dll file that receives network communication with information a (of type A). It calls the event D with a as input.
The main namespace registers myEventHandler to the event D fired by ExternalDll.
Inside myEventHanlder there is a lock, so the expected behavior is that the code inside the lock section is not executed more than once at any time.
However, when running the application, it sometimes reaches a situation that the locked code is executed twice "in parallel". For example, I might see printouts like:
First=0
First=1
Second=0
Second=1
This happens especially in cases of bursty network events that arrive within a very short time duration (<1us) to the externalDll.
My questions/requests are:
What could make the lock statement this faulty behavior. allowing 2 instances of the locked code ?
how to improve the code so that it gives the desired locking behavior.
Thanks,
-Moshe.
Don't know enough to say. A guess would be two app domains are being created because you are using something that spawns multiple app domains e.g. Asp.net sometimes does this for http modules.
Related
I'm trying to write a drawing library. In this drawing library there is an update function that should update every frame. I do this by using a do while loop See code below:
private void UpdateCanvas()
{
do
{
Canvas.PumpEvents();
if(UserUpdateVoid != null) UserUpdateVoid();
} while (Canvas.Exists);
}
I also have a function in which the user can set their own update function. This function is part of the SharpDraw class, see code below:
public void SetCustomUpdateFunction(Action function)
{
Console.WriteLine("updated the user function");
UserUpdateVoid = function;
Console.WriteLine(UserUpdateVoid);
}
all this is called in the following way:
public class SharpCanvas
{
private Sdl2Window Canvas;
private GraphicsDevice GraphicsManager;
private Action UserUpdateVoid = null;
public SharpCanvas()
{
WindowCreateInfo WindowInfo = new WindowCreateInfo(
200,
200,
100,
100,
WindowState.Normal,
"SharpWindow"
);
CreateCanvas(WindowInfo);
UpdateCanvas();
}
}
And the SharpDraw instance is made in the following way:
namespace test
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
SharpCanvas Canvas = new SharpCanvas(200,200);
Canvas.SetCustomUpdateFunction(Update);
}
private static void Update(){
Console.WriteLine("update");
}
}
}
But the problem is that the Console.Writelines in the SetCustomUpdateFunction() are never executed. I guess this has to do with the fact that the while loop keeps the program from further execution. So my question is how do i keep the while loop running while still being able to execute different pieces of code? In unity they are able to do it :P
If there is something unclear let me know so i can clarify!
That is entirely normal. It does not mater if you are running a console application, a Windows Form or WPF/UWP application*: Only one piece of code can be executing. While one piece of code does not return, not other code can run.
You need to add some form of Multitasking into the mix. Now that looks extremely like a Console Application and those are the last place I would advise learning Multithreading in. My personal advise is to start under Windows Forms using the BackgroundWorker. It is dated and rarely used in practice, but it can help you get up to speed with the rules and conventions. But this is one area where you can ask 10 people and get 11 Opinions.
*Web Applciations are semi special. As they are pleasingly parallel and it helps with isolation usually each request is given their own Thread. But at least for each singular request, it still holds true.
When you call UpdateCanvas, you enter a loop and code never goes further. To prevent this, you should use threads, async-await or something similar else (see this answer for async-await).
You have to use Multithreading programming. Look for it on google, there are plenty of examples.
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.
I'm trying to use this pre-made C# tftp server app with my windows c# form. In the authors server example, which works great, he uses a console app. When I trying porting his console example into my form app it doesn't work (no errors, just doesn't connect) and I believe my issue is in the "using" statement:
using (var server = new TftpServer())
{
server.OnReadRequest += new TftpServerEventHandler(server_OnReadRequest);
server.OnWriteRequest += new TftpServerEventHandler(server_OnWriteRequest);
server.Start();
Console.Read();
}
Not sure if I understand correctly but I believe the Console.Read() blocks keeping the app from exiting. If this is the case how would I implement a equivalent with a form app. I just can't get my head around the "using". Sorry I'm new to c#.
Windows Forms will always remain open until they're explicitly closed by the user. They always have a thread reading the message queue for user input, so they won't exit the same way an unrestrained console application will. In Windows Forms, we have to worry a bit more about multithreading and concurrency than we would in console apps. It mostly comes naturally, but not always.
Because of that, you can't really use an equivalent to Console.Read() to hold off execution of the using disposal until the user requests it. If you did, your form would simply appear unresponsive.
However, you're in luck! A using block in C# is nothing more than syntactic sugar for remembering to call IDisposable.Dispose() after you're done with an object. So the equivalent to this in a Forms project could just be storing the server object in a class-wide field, then calling server.Dispose() on, say, a Button.Click event. That's, of course, just an example. You could also do it on Form.Closing if that felt more appropriate.
High-level, you want to do something like this:
Declare a field in your form class TftpServer server;.
Register a Load event and whatever you need for your server to function in your constructor.
Open your server field in the Form_Load event.
Use the server's events as you see so fit during the life of your Form. You may or may not have to worry about concurrency, but that's a matter for another question.
Call server.Dispose() in the form's Dispose event.
In essence,
class main : Form
{
private TftpServer server;
public main()
{
InitializeComponent();
this.Load += main_Load;
server = new TftpServer();
server.OnReadRequest += new TftpServerEventHandler(server_OnReadRequest);
server.OnWriteRequest += new TftpServerEventHandler(server_OnWriteRequest);
}
private void main_Load(object sender, EventArgs e)
{
server.Start();
}
private void server_OnReadRequest(/* I wasn't sure of the arguments here */)
{
// use the read request: give or fetch its data (depending on who defines "read")
}
private void server_OnWriteRequest(/* I wasn't sure of the arguments here */)
{
// use the write request: give or fetch its data (depending on who defines "write")
}
protected override void Dispose(bool disposing)
{
if (server != null) // since Dispose can be called multiple times
{
server.Dispose();
server = null;
}
}
}
The problem is that disposing the server is what is closing it. Keep in mind using is just syntactic sugar. The following two code chunks are [practically] equivalent:
var foo = new Foo();
try
{
foo.Do();
}
finally
{
foo.Dispose();
}
using (var foo = new Foo())
{
foo.Do();
}
You are fine blocking the main thread from exiting in a Console app, but in a Forms app it's different. The problem is not that you need to hold the thread inside the using by doing some sort of blocking operation. That would be bad, and the behavior would lock up your forms app. The problem is you don't want to use using. You want to new it up when you start the server, and then later on, on application exit, or on a stop click, explicitly dispose it with Dispose().
In a console application your TftpServer instance is listening until the thread exits which is only after a key is pressed which is detected by Console.Read()
In your forms app that Console.Read() isn't waiting around and so the using block finishes and that causes your server instance to fall out of scope.
So you are not exactly misusing the using but rather the intended use is not helping you at all. Take a look at using the task parallel library to let some background tasks run asynchronously.
A small note that also doubles as an answer, you could use a using block here, you just put it in your main function:
...(make your form and stuff)
using (var server = new TftpServer())
{
server.OnReadRequest += new TftpServerEventHandler(server_OnReadRequest);
server.OnWriteRequest += new TftpServerEventHandler(server_OnWriteRequest);
server.Start();
Application.Run(yourFormHere); //This blocks until the form is closed
}
Another option I forgot to mention is overriding Dispose in your Form. You probably want to do this. With this option you're guaranteed your server will be disposed (bar some event that would prevent it from being disposed either way [ie. being out of memory])
I wrote this static log class to record all status during many threads. Sometimes I got a exception saying the log file(that the program is writing) was occupied. It seems other thread was writing the file at the same time. I made all this works invoke to UI thread to avoid this exception, but it still happens. Any suggestion? Thanks.
BTW, I know I may use lock(mLog) to avoid this problem, but I am still wondering why this happens, UI thread should never run 2 Log.UpdateLog functions at the same time, am I right?
public partial class LogForm : Form
{
private StringBuilder mLog;
public LogForm()
{
InitializeComponent();
mLog = new StringBuilder();
}
public void Write(string msg, bool save)
{
mLog.Insert(0, msg + "\r\n\r\n" + "-----------------------------------------------------------------------" + "\r\n\r\n");
if (save)
{
SaveFile();
}
}
private void SaveFile()
{
FileStream file;
file = new FileStream(Application.StartupPath + #"\LOG.txt", FileMode.Create);
StreamWriter sw = new StreamWriter(file);
sw.Write(mLog.ToString());
sw.Close();
file.Close();
}
}
public static class Log
{
private delegate void mUIInvoke(string msg, bool save);
private static LogForm mLogForm = new LogForm();
public static void Write(string msg, bool save)
{
msg += "\r\nTIME:" + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString();
if (mLogForm.InvokeRequired)
{
mUIInvoke invoke = new mUIInvoke(UpdateLog);
mLogForm.BeginInvoke(invoke, new object[] { msg, save });
}
else
{
UpdateLog(msg, save);
}
}
private static void UpdateLog(string msg, bool save)
{
mLogForm.Write(msg, save);
}
}
This is definitely not an elegant method for implementing logging as you've multiple threads in your class. If you want a better design, your logging stuffs has to be moved out from form class as logging is something independent and threads shouldn't access a "form" to "log" make it meaningful.
There are two alternatives for this.
Go for logging frameworks which are tested and proven like log4net or NLog
Make this logging class independant and create an instance (mostly a singleton though I am against singleton classes) of logger class and share it between multiple threads. file management, logging functions etc. has to be managed separately. All the operations has to be protected with thread synchronization mechanisms like mutex. There are several ways to implement a logging framework. It's all depends on how much of you really need!
Unless it's not a big deal or for learning purpose, I would suggest you to use existing logging frameworks, especially when using with production quality code.
It is not a problem of the UI thread. The problem is (mainly) in the SaveFile method. If two different threads try to access this method one could find the file still in use by the other thread. A simple lock could resolve the problem.
So immagine Thread A that call mLogForm.Write
It enters the method and reach without interruption the SaveFile method,
it open the file stream but at this point is interrupted and the OS decides to run Thread B
Thread B runs and reach the same SaveFile finding the File locked by the previous thread suspended
Here is a theory: your logging form is accessed through static variable. This variable is initialized on first access of the Log class, and this first access can happen from non-ui thread. So your form could be created on a non-ui thread, and this could cause the issues you are experiencing.
I figured out this problem with one of my friends.
Its actually because the mLogForm has never been showed before mLogForm.InvokeRequired is called. If its not showed, there will NEVER be a handle for mLogForm. Without handle, you will not be able to call mLogForm.InvokeRequired in its right way.
Which means it will return false even if other thread calls Log.Write
and then I got a lot threads running UpdateLog method, caused this problem.
To make sure you could use invoke to a unshowed form, use CreateHandle() while you create this form.
Thanks.
I read many posts saying multithreaded applications must use a separate session per thread. Perhaps I don't understand how the locking works, but if I put a lock on the session in all repository methods, would that not make a single static session thread safe?
like:
public void SaveOrUpdate(T instance)
{
if (instance == null) return;
lock (_session)
using (ITransaction transaction = _session.BeginTransaction())
{
lock (instance)
{
_session.SaveOrUpdate(instance);
transaction.Commit();
}
}
}
EDIT:
Please consider the context/type of applications I'm writing:
Not multi-user, not typical user-interaction, but a self-running robot reacting to remote events like financial data and order-updates, performing tasks and saves based on that. Intermittently this can create clusters of up to 10 saves per second. Typically it's the same object graph that needs to be saved every time. Also, on startup, the program does load the full database into an entity-object-graph. So it basically just reads once, then performs SaveOrUpdates as it runs.
Given that the application is typically editing the same object graph, perhaps it would make more sense to have a single thread dedicated to applying these edits to the object graph and then saving them to the database, or perhaps a pool of threads servicing a common queue of edits, where each thread has it's own (dedicated) session that it does not need to lock. Look up producer/consumer queues (to start, look here).
Something like this:
[Producer Threads]
Edit Event -\ [Database Servicer Thread]
Edit Event ------> Queue -> Dequeue and Apply to Session -> Database
Edit Event -/
I'd imagine that a BlockingCollection<Action<Session>> would be a good starting point for such an implementation.
Here's a rough example (note this is obviously untested):
// Assuming you have a work queue defined as
public static BlockingCollection<Action<Session>> myWorkQueue = new BlockingCollection<Action<Session>>();
// and your eventargs looks something like this
public class MyObjectUpdatedEventArgs : EventArgs {
public MyObject MyObject { get; set; }
}
// And one of your event handlers
public MyObjectWasChangedEventHandler(object sender, MyObjectUpdatedEventArgs e) {
myWorkQueue.Add(s=>SaveOrUpdate(e.MyObject));
}
// Then a thread in a constant loop processing these items could work:
public void ProcessWorkQueue() {
var mySession = mySessionFactory.CreateSession();
while (true) {
var nextWork = myWorkQueue.Take();
nextWork(mySession);
}
}
// And to run the above:
var dbUpdateThread = new Thread(ProcessWorkQueue);
dbUpdateThread.IsBackground = true;
dbUpdateThread.Start();
At least two disadvantages are:
You are reducing the performance significantly. Having this on a busy web server is like having a crowd outside a cinema but letting people go in through a person-wide entrance.
A session has its internal identity map (cache). A single session per application means that the memory consumption grows as users access different data from the database. Ultimately you can even end up with the whole database in the memory which of course would just not work. This requires then calling a method to drop the 1st level cache from time to time. However, there is no good moment to drop the cache. You just can't drop in at the beginning of a request because other concurrent sessions could suffer from this.
I am sure people will add other disadvantages.