File occupied by other thread - c#

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.

Related

Make main thread execute code on button press after form.show

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.

c# lock does not work (?)

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.

How do I generate keystrokes in a non-form application

So I have a huge program and decided I should make one of the methods run in a separate thread. So I put the method in a separate class, an activated it on my form. It seemed to worked just how I wanted it to until it got to part where it gave me this error:
SendKeys cannot run inside this application because the application
is not handling Windows messages. Either change the application to
handle messages, or use the SendKeys.SendWait method.
I tried looking for the answer online. I think I saw something about how SendKeys only works in a Form or something.
Can anyone tell me a way to simulate a keystroke without using SendKeys, OR a way to get SendKeys to work in a different, non-form thread?
Your console application needs a message loop. This is done through the Application class. You will need to call Application.Run(ApplicationContext).
class MyApplicationContext : ApplicationContext
{
[STAThread]
static void Main(string[] args)
{
// Create the MyApplicationContext, that derives from ApplicationContext,
// that manages when the application should exit.
MyApplicationContext context = new MyApplicationContext();
// Run the application with the specific context. It will exit when
// the task completes and calls Exit().
Application.Run(context);
}
Task backgroundTask;
// This is the constructor of the ApplicationContext, we do not want to
// block here.
private MyApplicationContext()
{
backgroundTask = Task.Factory.StartNew(BackgroundTask);
backgroundTask.ContinueWith(TaskComplete);
}
// This will allow the Application.Run(context) in the main function to
// unblock.
private void TaskComplete(Task src)
{
this.ExitThread();
}
//Perform your actual work here.
private void BackgroundTask()
{
//Stuff
SendKeys.Send("{RIGHT}");
//More stuff here
}
}
I Know this not an answer, but this how i used to do using ActiveX and Script
Set ws = CreateObject("WScript.Shell")
str = "Hi there... ~ Dont click your mouse while i am typing." & _
" ~~This is a send key example, using which you can send your keystrokes"
ws.Run("notepad.exe")
WScript.Sleep(1000)
For c=1 To Len(str)
WScript.Sleep(100) 'Increase the value for longer delay
ws.SendKeys Mid(str,c,1)
Next
Save this code as file.vbs and double click to execute in windows machine.

Managing disposable objects within static methods

public class SimpleLogger
{
static readonly string logFile = ConfigurationManager.AppSettings["LogFile"];
static StreamWriter GetStream()
{
return File.Exists(logFile) ?
File.AppendText(logFile) : File.CreateText(logFile);
}
public static void Write(string msg)
{
using (var sw = GetStream())
{
sw.Write(msg);
}
}
}
The above code fails in use as it doesn't appear to be closing/disposing of the stream correctly. Subsequent writes give a 'file in use' IOException.
If the class is modified to use non-static methods, it appears to work correctly.
I don't understand why there would be any behavioural difference?
The disposal is fine; GetStream delivers an open writer; Write closes/disposes it - sorted. if I had to guess, though, the issue is concurrent use - i.e. multiple threads (in particular in a web application) accessing the file at the same time. If that is the case, options:
make Write (and any other access to the file) synchronized, so only one caller can possibly try to have the file open at once
use a pre-canned logging framework that will already handle this scenario (common approaches here include synchronization, but also: buffering the data locally and then pushing the data down periodically - avoids opening the file over and over and over and over)
In particular; your only static state is the file path itself. There will therefore be no significant difference between using this as a static versus instance method.
As a side-note, File.AppendAllText may be useful here, but does not avoid the issue of concurrency.
I don't think changing from a static to an instance would fix the problem since they're all ultimately contending over a static resource (the file). This answer might help you. Perhaps if you left both methods static and declared a static synchronisation object for calling threads to lock with (since the resource is static itself) would help?, e.g.:
private static object _objectLock = new object();
for synchronising access to the file from multiple threads, hence:
public static void Write(string msg)
{
lock(_objectLock)
{
using (var sw = GetStream())
{
sw.Write(msg);
}
}
}

C# Am i using lock correctly?

I'm currently trying to write a thread-safe logger class. I'm not very familiar with correct design and best practices in this area. Is there a flaw in my code?
public class WriteStuff
{
private readonly StreamWriter m_Writer;
private readonly object m_WriteLock = new object ();
public WriteStuff(String path)
{
m_Writer = File.CreateText (path);
m_Writer.WriteLine ("x");
m_Writer.Flush ();
}
public void ListenTo(Foo foo)
{
foo.SomeEvent += new EventHandler<SomeArgs> (Foo_Update);
}
private void Foo_Update(object sender, SomeArgs args)
{
lock (m_WriteLock) {
m_Writer.WriteLine (args);
m_Writer.Flush ();
}
}
}
Well, that looks OK to me; I'd probably implement IDisposable as a means to Close() the file, but...
Of course, you could also use any of the (many) pre-canned logging frameworks.
Update:
One thought: you might want to consider what happens if the file already exists; you don't want to stomp on your logs...
What you've posted looks fine from a multi-threading perpective. Although I could be wrong, it would appear that any other code that does some multi-threading (even using the foo object) should be safe. Certainly, I can't see any deadlocks in the that section of code.
A few things worth noting anyway (apart from being very careful with deadlocks and testing rigourously to insure they won't occur):
It's best to put a lock around the code within the constructor, as I believe it's possible in certain circumstances that methods can be called before the constructor block has finished executing. (Someone please correct me if I'm wrong on this one.)
The StreamWriter object in this case is private, which is good. If it were protected or internal you would certainly have to be cautious about how other code utilised the object (in fact I think it would be best to almost always declare such objects as private).
You've done locking the right way! It's always safest to lock on a separate private instance object because you know that object can't be locked by any other code than your own (which isn't the case if you lock this or the StreamWriter object itself).
Still, I may be missing something, and there is a small possibility that some other code not shown above might cause problems, but as far as I can see it that code isn't flawed except for a possible missing lock around the constructor code. You're more likely to have to watch out for deadlock situations when you start doing more complex multi-threading, especially across classes/instances.
Anyway, hope that helps.
The event handler is on the same thread as the event generator which means your app could end up being held up by your log file write.
private void Foo_Update(object sender, SomeArgs args) {
ThreadPool.QueueUserWorkItem(WriteAsync, args);
}
private void WriteAsync(object state) {
SomeArgs args = (SomeArgs)state;
lock (m_WriteLock) {
m_Writer.WriteLine (args);
m_Writer.Flush ();
}
}

Categories

Resources