Delegate.BeginInvoke doesn't appear to do anything on a different PC - c#

private void button1_Click(object sender, EventArgs e)
{
this.icon_testLOAD.Visible = true;
this.icon_testOK.Visible = false;
this.icon_testBAD.Visible = false;
this.debug("Test Service Button Clicked");
rabbitmq_test t = new rabbitmq_test(button_rabbitmq_test);
this.debug("Calling BeginInvoke on button_rabbitmq_test delegate");
t.BeginInvoke(null, null);
}
So I have this button click event. The first three lines are turning on and off PictureBoxes that contain icons.
this.debug() merely calls EventLog.WriteEntry()
The button_rabbitmq_test method looks like:
protected void button_rabbitmq_test()
{
this.debug("Creating new rabbitmq connection factory");
IConnection connection;
try
{
ConnectionFactory rq_factory = new ConnectionFactory();
rq_factory.Port = Convert.ToInt16(this.psistats_config.rabbitmq_port);
rq_factory.HostName = this.psistats_config.rabbitmq_server;
rq_factory.UserName = this.psistats_config.rabbitmq_username;
rq_factory.Password = this.psistats_config.rabbitmq_password;
rq_factory.RequestedConnectionTimeout = 15000;
this.debug("Creating new rabbitmq connection");
connection = rq_factory.CreateConnection();
this.debug("Changing icon to successful");
rabbitmq_icon_delegate d = new rabbitmq_icon_delegate(this.testOK);
connection.Close();
this.test_button.Invoke(d);
}
catch (Exception exc)
{
if (connection != null)
{
connection.Close();
}
this.debug("Failed testing the rabbit server");
this.debug(exc.Message);
this.debug(exc.StackTrace);
rabbitmq_icon_delegate d = new rabbitmq_icon_delegate(this.testFailed);
this.test_button.Invoke(d);
}
}
This code works fine on the computer I'm doing the development on. The method executes, the event log is populated as expected. However, when I run this application on a second machine, the BeginInvoke method doesn't seem to do anything at all and I have absolutely no idea why.
The last message I see in the event log is "Calling BeginInvoke..." but the event logs from the method that performs the actual test are not seen anywhere.
The application is also not frozen. I can still use it.
I am at a loss as to what I am doing wrong and any advice would be welcome.

The code is fundamentally flawed, you must call the delegate's EndInvoke() method. Best done by not passing null as the first argument, use a callback method that then calls EndInvoke().
If you don't call EndInvoke() then you'll leak resources, lasts for 10 minutes. And the ultimate problem you are asking about, you can't see an exception that was raised by the method. So you cannot find out why it didn't work. Calling EndInvoke() rethrows that exception.
Using a delegate's BeginInvoke() method is a low-level programming technique that's best avoided, too easy to make mistakes like this and too difficult to deal with exceptions. Use a BackgroundWorker or a Task instead.

Related

C# winforms freezing: Serialport, Timer, Thread

Edit: Keeping the original question for continuity.
I then edited the question with replacement code for the ReadLine() method by using ReadExisting instead. It works however I still have the same freeze, where the app becomes unresponsive. Debug says it's locking (it takes a while to freeze, sometimes seconds, sometimes minutes) in the while () {} function where I wait for the complete message. More explanations below:
-- obsolete --
What is a good way to handle serialport.readtimeout exception?
try
{
serialPort1.Write(Command_);
if (!IsWriteComm_)
{
Response_ = serialPort1.ReadLine().Replace("\r", "");
}
}
catch (TimeoutException err)
{
DateTime d = DateTime.Now;
rtboxDiag.AppendText("\n" + d.ToString("HH:mm:ss") + ": ");
rtboxDiag.AppendText(err.Message);
if (!serialPort1.IsOpen)
InitConnection();
return Textbox_;
}
this bit of code is exectuted on a timer tick event.
I was having a weird "crash" of the app with an IO exception
"The I/O operation has been aborted because of either a thread exit or an application request."
no matter what I do I am not able to "recover" meaning, I am no longer able to poll data from the serial port.
I added this exception catch and it does log the exception. weirdly enough the test on !serialport.isopen is false (meaning the port is still open).
What might be a hint is: this error does STOP the timer somehow, this is not something I am doing in code. so I am suspecting something related to the timer, rather than the serialport, but I could be wrong.
Closing the port manually, and reconnecting does not fix the problem.
Disconnecting and reconnecting the USB does not fix the problem.
however, closing the app, and relaunching the app does fix the problem (without even disconnecting the MCU or power cycling the MCU/hardware).
-- /obsolete --
edit: the problem is appearing after a few seconds, sometimes minutes of flawless operations. I cannot repeat the issue using a serialport terminal polling the data the same way, at the same frequency. It seems the problem is not coming from the hardware itself.
cheers
Edit: I have yet to test the following modification, not sure if it will fix this problem (I doubt), but at least it's an attempt at not using .readline() which from what I've gathered is not good practice.
anyway here it is:
try
{
serialPort1.Write(Command_);
if (!IsWriteComm_)
{
while (!SerialRxCplt) ;
Response_ = SerialRxResponse.Replace("\r", "").Replace("\n", "");
SerialRxCplt = false;
//Response_ = serialPort1.ReadLine().Replace("\r", "");
}
}
catch (TimeoutException err)
{
DateTime d = DateTime.Now;
rtboxDiag.AppendText("\n" + d.ToString("HH:mm:ss") + ": ");
rtboxDiag.AppendText(err.Message);
if (!serialPort1.IsOpen)
InitConnection();
return Textbox_;
}
and I have the datareceived event enabled:
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
var serialPort = (System.IO.Ports.SerialPort)sender;
string dataReceived = serialPort.ReadExisting();
ProcessSerialData(dataReceived);
}
and this is how I am processing the data, and manually "waiting" for the \n character which tells me when the data has been fully received.
private void ProcessSerialData(string data)
{
SerialRxBuffer += data;
if (SerialRxBuffer.Contains("\n"))
{
SerialRxCplt = true;
SerialRxResponse = SerialRxBuffer;
SerialRxBuffer = "";
}
else
{
SerialRxCplt = false;
}
}
any input is welcome.
I have added "stuff" for debugging inside that while loop and it does work fine for a while and then freezes, no error or exception is thrown there. For some reason I have a feeling it's not related to the serial port.
I have even added this:
try
{
serialPort1.Write(Command_);
if (!IsWriteComm_)
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
while (!SerialRxCplt || Timer2StopWatchMilli > 5)
{
Timer2StopWatchMilli = stopWatch.Elapsed.TotalMilliseconds;
ExceptionMessage = Timer2StopWatchMilli.ToString();
IsException = true;
}
stopWatch.Stop();
if (!SerialRxCplt)
return Textbox_;
Response_ = SerialRxResponse.Replace("\r", "").Replace("\n", "");
SerialRxCplt = false;
//Response_ = serialPort1.ReadLine().Replace("\r", "");
}
}
the ExceptionMessage and IsException help me have an idea of what's happening in that loop. And in normal operations, it is what you would except, increments in the order of 0.0x milliseconds. Data is being processed correctly. When it freezes, nothing looks abnormal. I initially thought I was somehow getting "stuck" in an infinite loop but that || Timer2StopWatchMilli > 5 should get me out of it, acting as some sort of timeout.
one extra piece of info: when it freezes, the one CPU core is fully loaded. (I have a 6core CPU, and it's 16-17% in the task manager - memory usage is low < 30MB)
Any help is welcome
I fixed it by clearing RX/TX and stream buffers after each successful transaction.
I think data was being sent to the PC faster than it was able to read causing data to eventually accumulating on the Rx Buffer.
private void SerialPortClearBuffers()
{
serialPort1.DiscardOutBuffer();
serialPort1.DiscardInBuffer();
serialPort1.BaseStream.Flush();
}

WCF TimeoutException despite stepping through showing successful return

I have two self hosted services running on the same network. The first is sampling an excel sheet (or other sources, but for the moment this is the one I'm using to test) and sending updates to a subscribed client.
The second connects as a client to instances of the first client, optionally evaluates some formula on these inputs and the broadcasts the originals or the results as updates to a subscribed client in the same manner as the first. All of this is happening over a tcp binding.
My problem is occuring when the second service attempts to subscribe to two of the first service's feeds at once, as it would do if a new calculation is using two or more for the first time. I keep getting TimeoutExceptions which appear to be occuring when the second feed is subscribed to. I put a breakpoint in the called method on the first server and stepping through it, it is able to fully complete and return true back up the call stack, which indicates that the problem might be some annoying intricacy of WCF
The first service is running on port 8081 and this is the method that gets called:
public virtual bool Subscribe(int fid)
{
try
{
if (fid > -1 && _fieldNames.LeftContains(fid))
{
String sessionID = OperationContext.Current.SessionId;
Action<Object, IUpdate> toSub = MakeSend(OperationContext.Current.GetCallbackChannel<ISubClient>(), sessionID);//Make a callback to the client's callback method to send the updates
if (!_callbackList.ContainsKey(fid))
_callbackList.Add(fid, new Dictionary<String, Action<Object, IUpdate>>());
_callbackList[fid][sessionID] = toSub;//add the callback method to the list of callback methods to call when this feed is updated
String field = GetItem(fid);//get the current stored value of that field
CheckChanged(fid, field);//add or update field, usually returns a bool if the value has changed but also updates the last value reference, used here to ensure there is a value to send
FireOne(toSub, this, MakeUpdate(fid, field));//sends an update so the subscribing service will have a first value
return true;
}
return false;
}
catch (Exception e)
{
Log(e);//report any errors before returning a failure
return false;
}
}
The second service is running on port 8082 and is failing in this method:
public int AddCalculation(string name, string input)
{
try
{
Calculation calc;
try
{
calc = new Calculation(_fieldNames, input, name);//Perform slow creation before locking - better wasted one thread than several blocked ones
}
catch (FormatException e)
{
throw Fault.MakeCalculationFault(e.Message);
}
lock (_calculations)
{
int id = nextID();
foreach (int fid in calc.Dependencies)
{
if (!_calculations.ContainsKey(fid))
{
lock (_fieldTracker)
{
DataRow row = _fieldTracker.Rows.Find(fid);
int uses = (int)(row[Uses]) + 1;//update uses of that feed
try
{
if (uses == 1){//if this is the first use of this field
SubServiceClient service = _services[(int)row[ServiceID]];//get the stored connection (as client) to that service
service.Subscribe((int)row[ServiceField]);//Failing here, but only on second call and not if subscribed to each seperately
}
}
catch (TimeoutException e)
{
Log(e);
throw Fault.MakeOperationFault(FaultType.NoItemFound, "Service could not be found");//can't be caught, if this timed out then outer connection timed out
}
_fieldTracker.Rows.Find(fid)[Uses] = uses;
}
}
}
return id;
}
}
catch (FormatException f)
{
Log(f.Message);
throw Fault.MakeOperationFault(FaultType.InvalidInput, f.Message);
}
}
The ports these are on could change but are never shared. The tcp binding used is set up in code with these settings:
_tcpbinding = new NetTcpBinding();
_tcpbinding.PortSharingEnabled = false;
_tcpbinding.Security.Mode = SecurityMode.None;
This is in a common library to ensure they both have the same set up, which is also a reason why it is declared in code.
I have already tried altering the Service Throttling Behavior for more concurrent calls but that didn't work. It's commented out for now since it didn't work but for reference here's what I tried:
ServiceThrottlingBehavior stb = new ServiceThrottlingBehavior
{
MaxConcurrentCalls = 400,
MaxConcurrentSessions = 400,
MaxConcurrentInstances = 400
};
host.Description.Behaviors.RemoveAll<ServiceThrottlingBehavior>();
host.Description.Behaviors.Add(stb);
Has anyone had similar issues of methods working correctly but still timing out when sending back to the caller?
This was a difficult problem and from everything I could tell, it is an intricacy of WCF. It cannot handle one connection being reused very quickly in a loop.
It seems to lock up the socket connection, though trying to add GC.Collect() didn't free up whatever resources it was contesting.
In the end the only way I found to work was to create another connection to the same endpoint for each concurrent request and perform them on separate threads. Might not be the cleanest way but it was all that worked.
Something that might come in handy is that I used the svc trace viewer to monitor the WCF calls to try and track the problem, I found out how to use it from this article: http://www.codeproject.com/Articles/17258/Debugging-WCF-Apps

TcpClient.EndConnect throws NullReferenceException when socket is closed

I am trying to connect to my server with a TcpClient.BeginConnect / TcpClient.EndConnect combo. However, some things don't work as they should.
The scenario is as follows:
Call to the TcpClient.BeginConnect
Server is intentionally offline (for testing purposes) - thus no connection can be made.
I close the application (client.Close() gets called in the process which closes the socket which in turn stops the async operation)
TcpClient connection callback method happens giving IAsyncResult
Call to the TcpClient.EndConnect method with the given IAsyncResult
NullReferenceException happens on EndConnect (?)
Since the last form (window) was closed, the app should exit - however it does not, at least not until BeginConnect operation completes (which is strange, as callback has already been called).
What happens here is that a NullReferenceException is caught. As you can see from the picture above, neither client nor ar are null. The problem is that the MSDN documentation for the EndConnect does not mention the case in which this exception is thrown.
So basically, I have no idea what is going on. The problem is that I am forced to wait for the app to close (as if the connection operation still waits for a timeout). If a server is online, it connects and disconnects just fine.
What does NullReferenceException in this context mean? How to avoid BeginConnect operation to block the application closing in case the connection can't be established?
Additional notes (requested in comments):
Here is the code to create the client (client is a member variable:
public void Connect()
{
try
{
lock (connectionAccess)
{
if (State.IsConnectable())
{
// Create a client
client = new TcpClient();
client.LingerState = new LingerOption(false, 0);
client.NoDelay = true;
State = CommunicationState.Connecting;
client.BeginConnect(address, port, onTcpClientConnectionEstablished, null);
}
else
{
// Ignore connecting request if a connection is in a state that is not connectable
}
}
}
catch
{
Close(true);
}
}
Also the Close method:
public void Close(bool causedByError)
{
lock (connectionAccess)
{
// Close the stream
if (clientStream != null)
clientStream.Close();
// Close the gateway
if (client != null)
client.Close();
// Empty the mailboxes
incomingMailbox.Clear();
outgoingMailbox.Clear();
State = causedByError ? CommunicationState.CommunicationError : CommunicationState.Disconnected;
}
}
The NullReferenceException is probably due to TcpClient.Client being null.
If you were to follow the MSDN Example for TcpClient.BeginConnect and pass theTcpClient object as the state object:
private void onConnEst(IAsyncResult ar)
{
try
{
TcpClient client = (TcpClient)ar.AsyncState;
if(client!=null && client.Client!=null)
{
client.EndConnect(ar);
}
}
catch(Exception ex){...}
}
This should handle the case when Close() is called before the Callback.
Going back to your problem - how long does it take for the application to eventually close?
This obviously a bug inside the TcpClient class. I have also faced it. TcpClient.Dispose may set Client field to null but EndConnect does not expect that.
I had a similar error and ended up using this code. I am not sure if it will hold with the IASyncResult interface, but there may be a similar way to run this check. I do notice that your ar.AsyncState == null, so perhaps try starting there, i.e. is it null when you connect properly?
private void connConnectCompleted(AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
// Something didn't work...abort captain
CloseSocket();
Console.WriteLine(this.GetType().ToString() + #":Error connecting socket:" + e.Error.Message);
return;
}
// Do stuff with your connection
}
EDIT: Sorry I didn't realise I didn't post what generated my AsyncCompletedEventArgs, which is more related to what you are doing. You will see the reason why I was wondering as to ar.AsyncState being null.
private void OnConnect(IAsyncResult asyncResult)
{
if (OnConnectCompleted == null) return; // Check whether something is using this wrapper
AsyncCompletedEventArgs args;
try
{
Socket outSocket = (Socket) asyncResult.AsyncState;
// Complete connection
outSocket.EndConnect(asyncResult);
args = new AsyncCompletedEventArgs(null);
OnConnectCompleted(this, args);
}
catch (Exception e)
{
args = new AsyncCompletedEventArgs(e.Message);
OnConnectCompleted(this, args);
}
}
This is a know bug.
You should be receiving 'ObjectDisposedException' instead of 'NullReferenceException'.

How to catch a Lua exception in C#

I am using the an assembly named LuaInterface to run lua-code inside my C# application. During the lua execution I create some WinForms & map event handlers (lua-methods) to them.
The problem is that the doString (aka runLuaCode) method only runs the init routine and the constructors. This is fine and intended, however the doString function acts non blocking so the function returns while the Lua-created-Forms are still there. This means that any exception (null-ref and alike) which is not raised during the constructor is not handled by the lua error handling an crashes all the way up to my wndProc of my Editor - which most likely kills my editor and make error handling virtually impossible.
Is there any way to create a new Thread / Process / AppDomain that handles it's own WndProc so that only this sub-task needs to handle the exceptions?
Should I block my Editor at the doString with a while loop in lua until the forms are closed?
What other options do I have?
Any advice on this matter is greatly appreciated!
Another Lua enthusiast!! Finally! :) I am also toying with the idea to use Lua for macro scripting in my .NET apps.
I am not sure I get it. I wrote some sample code and it seems to be working ok. Simple try catch around DoString gets the LuaExceptions. DoString does block the main thread unless you explicitly create a new thread. In case of a new thread normal .NET multithreaded exception handling rules apply.
Example:
public const string ScriptTxt = #"
luanet.load_assembly ""System.Windows.Forms""
luanet.load_assembly ""System.Drawing""
Form = luanet.import_type ""System.Windows.Forms.Form""
Button = luanet.import_type ""System.Windows.Forms.Button""
Point = luanet.import_type ""System.Drawing.Point""
MessageBox = luanet.import_type ""System.Windows.Forms.MessageBox""
MessageBoxButtons = luanet.import_type ""System.Windows.Forms.MessageBoxButtons""
form = Form()
form.Text = ""Hello, World!""
button = Button()
button.Text = ""Click Me!""
button.Location = Point(20,20)
button.Click:Add(function()
MessageBox:Show(""Clicked!"", """", MessageBoxButtons.OK) -- this will throw an ex
end)
form.Controls:Add(button)
form:ShowDialog()";
private static void Main(string[] args)
{
try
{
var lua = new Lua();
lua.DoString(ScriptTxt);
}
catch(LuaException ex)
{
Console.WriteLine(ex.Message);
}
catch(Exception ex)
{
if (ex.Source == "LuaInterface")
{
Console.WriteLine(ex.Message);
}
else
{
throw;
}
}
Console.ReadLine();
}
LuaInterface has a pretty good documentation where tricky error handling is explained.
http://penlight.luaforge.net/packages/LuaInterface/#T6
I hope it helps. :)

Variable mysteriously changing value

EDIT: Ok I had a problem with one of the string concatenation functions, has nothing to do with threads, but knowing that it couldn't be a problem with threading lead me to the answer thank you for answering.
I am making a simple tcp/ip chat program for practicing threads and tcp/ip. I was using asynchronous methods but had a problem with concurrency so I went to threads and blocking methods (not asynchronous). I have two private variables defined in the class, not static:
string amessage = string.Empty;
int MessageLength;
and a Thread
private Thread BeginRead;
Ok so I call a function called Listen ONCE when the client starts:
public virtual void Listen(int byteLength)
{
var state = new StateObject {Buffer = new byte[byteLength]};
BeginRead = new Thread(ReadThread);
BeginRead.Start(state);
}
and finally the function to receive commands and process them, I'm going to shorten it because it is really long:
private void ReadThread(object objectState)
{
var state = (StateObject)objectState;
int byteLength = state.Buffer.Length;
while (true)
{
var buffer = new byte[byteLength];
int len = MySocket.Receive(buffer);
if (len <= 0) return;
string content = Encoding.ASCII.GetString(buffer, 0, len);
amessage += cleanMessage.Substring(0, MessageLength);
if (OnRead != null)
{
var e = new CommandEventArgs(amessage);
OnRead(this, e);
}
}
}
Now, as I understand it only one thread at a time will enter BeginRead, I call Receive, it blocks until I get data, and then I process it. The problem: the variable amessage will change it's value between statements that do not touch or alter the variable at all, for example at the bottom of the function at: if (OnRead != null) "amessage" will be equal to 'asdf' and at if (OnRead != null) "amessage" will be equal to qwert. As I understand it this is indicative of another thread changing the value/running asynchronously. I only spawn one thread to do the receiving and the Receive function is blocking, how could there be two threads in this function and if there is only one thread how does amessage's value change between statements that don't affect it's value. As a side note sorry for spamming the site with these questions but I'm just getting a hang of this threading story and it's making me want to sip cyanide.
Thanks in advance.
EDIT:
Here is my code that calls the Listen Method in the client:
public void ConnectClient(string ip,int port)
{
client.Connect(ip,port);
client.Listen(5);
}
and in the server:
private void Accept(IAsyncResult result)
{
var client = new AbstractClient(MySocket.EndAccept(result));
var e = new CommandEventArgs(client, null);
Clients.Add(client);
client.Listen(5);
if (OnClientAdded != null)
{
var target = (Control) OnClientAdded.Target;
if (target != null && target.InvokeRequired)
target.Invoke(OnClientAdded, this, e);
else
OnClientAdded(this, e);
}
client.OnRead += OnRead;
MySocket.BeginAccept(new AsyncCallback(Accept), null);
}
All this code is in a class called AbstractClient. The client inherits the Abstract client and when the server accepts a socket it create's it's own local AbstractClient, in this case both modules access the functions above however they are different instances and I couldn't imagine threads from different instances combining especially as no variable is static.
Well, this makes no sense the way you described it. Which probably means that what you think is going on is not what is really happening. Debugging threaded code is quite difficult, very hard to capture the state of the program at the exact moment it misbehaves.
A generic approach is to add logging to your code. Sprinkle your code with Debug.WriteLine() statements that shows the current value of the variable, along with the thread's ManagedId. You get potentially a lot of output, but somewhere you'll see it going wrong. Or you get enough insight in how thread(s) are interacting to guess the source of the problem.
Just adding the logging can in itself solve the problem because it alters the timing of code. Sucks when that happens.
I assume OnRead is firing an event dispatched on a thread pool thread. If any registered event handler is writing to amessage, its value could change any time you're in the reading loop.
Still not very clear where you are gettingthe value assigned to amessage in the loop. Should cleanmessage read content?

Categories