I am planning to use RabbitMQ in one of our projects at work.
I am evaluating different kinds of clients and wondering whether MassTransit can answer one of our needs regarding scalability.
I wrote a simple code below:
public class MyMessage
{
public string SomeText { get; set; }
}
public static class Program
{
public static async Task Main(params string[] args)
{
var counter = 0;
var bus = Bus.Factory.CreateUsingRabbitMq(busFactoryConfigurator =>
{
var host = busFactoryConfigurator.Host(new Uri("rabbitmq://localhost"), hostConfigurator =>
{
hostConfigurator.Username("guest");
hostConfigurator.Password("guest");
});
busFactoryConfigurator.ReceiveEndpoint(host, "test_queue", endpointConfigurator =>
{
endpointConfigurator.Handler<MyMessage>(async context =>
{
var countDoku = counter;
counter++;
await Console.Out.WriteLineAsync(countDoku.ToString() + ": started " + Thread.CurrentThread.ManagedThreadId);
await Task.Delay(500);
await Console.Out.WriteLineAsync(countDoku.ToString() + ": done " + Thread.CurrentThread.ManagedThreadId);
await Console.Out.WriteLineAsync($"Received: {context.Message.SomeText}");
});
});
});
await bus.StartAsync();
Parallel.ForEach(Enumerable.Repeat(42, 5000), async _ => await bus.Publish(new MyMessage {SomeText = "Hi"}));
Console.ReadKey();
await bus.StopAsync();
}
}
It's far from being the perfect benchmark (e.g. Console, Parallel.ForEach just use to throw as many async operations in parallel as possible) but putting that aside I've noticed something a bit embarrassing:
0: started 14
1: started 4
2: started 15
3: started 18
4: started 4
5: started 14
6: started 6
7: started 15
12: started 15
13: started 6
10: started 4
11: started 5
8: started 18
9: started 14
14: started 15
15: started 6
0: done 6
Received: Hi
5: done 14
6: done 5
Received: Hi
3: done 13
Received: Hi
12: done 8
Received: Hi
Received: Hi
7: done 18
Received: Hi
2: done 4
Received: Hi
4: done 15
Received: Hi
1: done 18
Received: Hi
11: done 18
Received: Hi
8: done 5
Received: Hi
9: done 14
Received: Hi
10: done 6
Received: Hi
13: done 4
Received: Hi
14: done 8
Received: Hi
15: done 15
Received: Hi
16: started 15
17: started 15
18: started 8
19: started 4
20: started 8
21: started 15
22: started 4
23: started 5
24: started 18
25: started 5
26: started 6
31: started 14
28: started 18
29: started 5
30: started 4
27: started 13
18: done 14
Received: Hi
17: done 13
Received: Hi
16: done 5
The handling part cannot process more than around 15 items at the same time...
I was wondering this is an issue with my benchmark code or a limitation in MassTransit configuration? Should I use an actor framework to better dispatch the load of items received from the queue in order to process more items at the same time?
Related
I have a device that spits out data in burst-mode about twice per second.
Each reading is a fairly long byte string something like:
0x0200c800013e7f4a643e7f766e3e7f8dfc3e7f6c603e7f59dc3e7f60663e7f57903e7f5f823e7f502e3e7f60303e7f612c3e7f61683e7f43923e7f4abe3e7f7cda3e7f5d783d392f383e7f4af43e7f68703e7f59be3e7f531c3e7f60783e7f62a03e7f6c903e7f7a883e7f4d523e7f4e783e7f3a983e7f6fba3e7f52aa3e7f6d983e7f6f543e7f6ae03d392a703e7f750c3e7f6c423e7f64a43e7f4f323e7f61863e7f60a83e7f711c3e7f81483e7f68
Anyways, from what I'm reading on the device documentation is that every "full package" will have 207 bytes, starting with a 02 that's the first byte (Start of Frame) and ends in a 7E (End of Frame) and there are some parsing methods to xOR these 2 "key bytes".
My problem comes when I trigger the "Received data" from module method:
private void DirectModule_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string resultSeed = "";
byte data;
rxDataBufferRawSeed.Clear();
if (isModuleHardwired)
{
Console.WriteLine("USB Module Data Received:");
while (directUSBPort.BytesToRead != 0)
{
data = (byte)directUSBPort.ReadByte();
rxDataBufferRawSeed.Add(data);
}
resultSeed = ByteArrayToString(rxDataBufferRawSeed.ToArray());
resultSeed = String.Concat(resultSeed.Where(c => !Char.IsWhiteSpace(c)));
Console.WriteLine("SEED RESULT: "+resultSeed);
}
}
Sometimes (I mean often) This code gets me a string that starts with 00 instead of 02 (meaning that 02 got lost somewhere? or what happened to it?) This causes issues since I start getting intermittent readings, instead of 2x per second, I start getting 1 every 3 or 1 every 5 seconds.
I don't really understand how this could happen. I'm sure that this is very volatile and not always exactly the same.
I have the following code, there is one core method and another method to call the core methods simultaneously by starting multiple Tasks, each Task calling 1 core method.
//here is the core method
public static bool ImportToSql(string targetConnectionString, IEnumerable<SyncedItem> accessFileItems)
{
var completelyOk = true;
using (var con = new SqlConnection(targetConnectionString))
{
foreach (var a in accessFileItems)
{
Log.WriteOnToday($"Syncing file: {a.Filename} ...");
var query = "some query here ...";
var retries = -1;
while (++retries <= 10)
{
if(retries > 0)
{
Thread.Sleep(60000);
Log.WriteOnToday($"Retrying to sync the file: \"{a.Filename}\" ({retries}/{10}) ...");
}
var r = ...;//do something here returning bool result
completelyOk &= r;
if (r)
{
break;
} else if(retries == 10)
{
Log.WriteOnToday($"FAILED to synce the file \"{a.Filename}\" after {10} retries");
}
}
}
}
return completelyOk;
}
//here is another method, actually the test data is grouped in 2 groups
//corresponding to 2 Tasks
public static async Task<bool> ParallelImportToSql(string targetConnectionString, IEnumerable<SyncedItem> accessFileItems)
{
IEnumerable<Task<bool>> tasks = accessFileItems.Select((e, i) => new { e, i })
.GroupBy(e => e.i % 2, (key,items) => items.Select(e => e.e))
.Select(g => Task.Run<bool>(() => ImportToSql(targetConnectionString, g)));
return (await Task.WhenAll(tasks)).All(e => e);
}
So you can see that there is one call to Log.WriteOnToday to log "Retrying ..." and I expect that should always be called (per my test the r is always false) and write exactly one corresponding line to the output file. So if it runs 10 times, there should be 10 lines. But actually there is one line missing in the output result. I really wonder how that could happen, could you analyze the code here and identify which could be wrong?
Here is the output result (written by Log.WriteOnToDay for "Retrying..."):
4/12/2018 5:28:05 PM - HO-IT1 >> Syncing file: \\192.168.0.144\DataKH_311\11_04_2018\cust.mdb ...
4/12/2018 5:29:05 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\11_04_2018\cust.mdb" (1/10) ...
4/12/2018 5:29:05 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\SVR\cust.mdb" (1/10) ...
4/12/2018 5:30:45 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\11_04_2018\cust.mdb" (2/10) ...
4/12/2018 5:32:25 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\11_04_2018\cust.mdb" (3/10) ...
4/12/2018 5:32:25 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\SVR\cust.mdb" (3/10) ...
4/12/2018 5:34:05 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\SVR\cust.mdb" (4/10) ...
4/12/2018 5:34:05 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\11_04_2018\cust.mdb" (4/10) ...
4/12/2018 5:35:45 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\SVR\cust.mdb" (5/10) ...
4/12/2018 5:35:45 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\11_04_2018\cust.mdb" (5/10) ...
4/12/2018 5:37:25 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\SVR\cust.mdb" (6/10) ...
4/12/2018 5:37:26 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\11_04_2018\cust.mdb" (6/10) ...
4/12/2018 5:39:06 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\SVR\cust.mdb" (7/10) ...
4/12/2018 5:39:06 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\11_04_2018\cust.mdb" (7/10) ...
4/12/2018 5:40:46 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\SVR\cust.mdb" (8/10) ...
4/12/2018 5:40:46 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\11_04_2018\cust.mdb" (8/10) ...
4/12/2018 5:42:26 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\SVR\cust.mdb" (9/10) ...
4/12/2018 5:42:26 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\11_04_2018\cust.mdb" (9/10) ...
4/12/2018 5:44:06 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\SVR\cust.mdb" (10/10) ...
4/12/2018 5:44:06 PM - HO-IT1 >> Retrying to sync the file: "\\192.168.0.144\DataKH_311\11_04_2018\cust.mdb" (10/10) ...
4/12/2018 5:44:46 PM - HO-IT1 >> FAILED to synce the file "\\192.168.0.144\DataKH_311\SVR\cust.mdb" after 10 retries
4/12/2018 5:44:46 PM - HO-IT1 >> FAILED to synce the file "\\192.168.0.144\DataKH_311\11_04_2018\cust.mdb" after 10 retries
There are just 2 files (mdb files to be synced to sql) including \\192.168.0.144\DataKH_311\SVR\cust.mdb and \\192.168.0.144\DataKH_311\11_04_2018\cust.mdb. The second file has all 10 logging lines output OK (as expected) BUT the first file has just 9 logging lines, the second line (corresponding to the second retry) is missing (for no reason). If looking at the time, you can see that there is almost a double gap (compared to other continuous pairs of logging lines of the same file) between the first (1/10) and the third (3/10) logging lines (for the first file I mentioned above). So looks like it's not just a simple by-passing.
It's not very important to miss that logging line, but in some other case if something important (some line of code) is by-passed here, that could cause a very hidden error (and of course that's very serious and unacceptable).
Update
The problem might be in the Log.WriteOnToDay, here is its code:
public static class Log
{
public static string LastWrittenLogFileName { get; private set; }
public static void WriteOnToday(string message, bool prependedWithDate = true, bool includeMachineInfo = true, string logFilePrefix = "log_")
{
Write(message, prependedWithDate, includeMachineInfo, string.Format(#"Logs\{0}{1:ddMMyyyy}.txt", logFilePrefix, DateTime.Now));
}
public static void Write(string message, bool prependedWithDate = true, bool includeMachineInfo = true, string filename = "log.txt")
{
//check for relative path in a simple way
if (Path.GetPathRoot(filename).Length < 3)
{
if (_currentDirectory == null)
{
_currentDirectory = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
}
filename = System.IO.Path.Combine(_currentDirectory, filename);
}
LastWrittenLogFileName = filename;
var dateText = "";
var machineInfo = "";
if (prependedWithDate) dateText = DateTime.Now + " - ";
if (includeMachineInfo) machineInfo = Environment.MachineName + " >> ";
message = string.Format("{0}{1}{2}", dateText, machineInfo, message);
var dir = Path.GetDirectoryName(filename);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
try
{
using (var sw = File.AppendText(filename))
{
sw.WriteLine(message);
}
}
catch
{
}
}
}
The catch above might be where the exception is swallow. Some IOException could be thrown there. Really I think that should rarely happen (unless there is something wrong with the hard disk drive).
Using Mono 4.6.1 and Xamarin Studio [Community] running on MBP with OSX 10.11.6
I have a Solution, with two projects; one is the .NET project, the other NUnit test project for the first. When I mock an interface which uses auto properties (using Moq or NSubstitute) it causes mono to crash (SIGSTOP) during debugging.
public interface IExample
{
string Name { get; }
}
[TestFixture]
public class Test
{
[Test]
public void TestCase()
{
var example = Substitute.For<IExample>();
example.Name.Returns("Hat");
Console.WriteLine(example.Name);
}
}
If I put a breakpoint on the first line which creates the example substitute the system waits as expected. If I step over that line after about 1-2 seconds the system crashes (details below). NB: Running the test causes the test to pass because it doesn't take long enough for the background failure to trigger.
Application Output of failure:
Loaded assembly: /Applications/Xamarin Studio.app/Contents/Resources/lib/monodevelop/AddIns/MonoDevelop.UnitTesting/NUnit2/NUnitRunner.exe
Loaded assembly: /Library/Frameworks/Mono.framework/Versions/4.6.1/lib/mono/gac/System/4.0.0.0__b77a5c561934e089/System.dll
Loaded assembly: /Applications/Xamarin Studio.app/Contents/Resources/lib/monodevelop/AddIns/MonoDevelop.UnitTesting/NUnit2/nunit.core.interfaces.dll
Loaded assembly: /Applications/Xamarin Studio.app/Contents/Resources/lib/monodevelop/AddIns/MonoDevelop.UnitTesting/NUnit2/nunit.core.dll
Loaded assembly: /Applications/Xamarin Studio.app/Contents/Resources/lib/monodevelop/AddIns/MonoDevelop.UnitTesting/NUnit2/nunit.framework.dll
Loaded assembly: /Applications/Xamarin Studio.app/Contents/Resources/lib/monodevelop/AddIns/MonoDevelop.UnitTesting/NUnit2/nunit.util.dll
Loaded assembly: /Library/Frameworks/Mono.framework/Versions/4.6.1/lib/mono/gac/System.Runtime.Remoting/4.0.0.0__b77a5c561934e089/System.Runtime.Remoting.dll
Loaded assembly: /Library/Frameworks/Mono.framework/Versions/4.6.1/lib/mono/gac/System.Configuration/4.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll
Loaded assembly: /Library/Frameworks/Mono.framework/Versions/4.6.1/lib/mono/gac/System.Xml/4.0.0.0__b77a5c561934e089/System.Xml.dll
Loaded assembly: /Library/Frameworks/Mono.framework/Versions/4.6.1/lib/mono/gac/Mono.Security/4.0.0.0__0738eb9f132ed756/Mono.Security.dll
Thread started: #2
Loaded assembly: /Library/Frameworks/Mono.framework/Versions/4.6.1/lib/mono/gac/System.Core/4.0.0.0__b77a5c561934e089/System.Core.dll
Thread started: #3
Thread started: <Thread Pool> #4
Thread started: <Thread Pool> #5
Thread started: <Thread Pool> #6
Loaded assembly: /Library/Frameworks/Mono.framework/Versions/4.6.1/lib/mono/gac/System.Drawing/4.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
Loaded assembly: /Library/Frameworks/Mono.framework/Versions/4.6.1/lib/mono/gac/nunit.util/2.4.8.0__96d09a1eb7f44a77/nunit.util.dll
Loaded assembly: /Library/Frameworks/Mono.framework/Versions/4.6.1/lib/mono/gac/nunit.core.interfaces/2.4.8.0__96d09a1eb7f44a77/nunit.core.interfaces.dll
Thread started: #7
Loaded assembly: /Users/jeremy.connor/dev/MonoAPBug/MonoAPBug.Tests/bin/Debug/MonoAPBug.Tests.dll
Thread started: EventPumpThread #8
Thread started: TestRunnerThread #9
Resolved pending breakpoint at 'Test.cs:13,1' to void MonoAPBug.Tests.Test.TestCase () [0x00001].
Loaded assembly: /Users/jeremy.connor/dev/MonoAPBug/MonoAPBug.Tests/bin/Debug/MonoAPBug.exe
Loaded assembly: /Users/jeremy.connor/dev/MonoAPBug/MonoAPBug.Tests/bin/Debug/NSubstitute.dll
Loaded assembly: /Library/Frameworks/Mono.framework/Versions/4.6.1/lib/mono/gac/System.ServiceModel/4.0.0.0__b77a5c561934e089/System.ServiceModel.dll
Loaded assembly: DynamicProxyGenAssembly2
Loaded assembly: DynamicProxyGenAssembly2
mono(10800,0xb0319000) malloc: *** error for object 0x77c2a0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Stacktrace:
Native stacktrace:
0 mono 0x00171e46 mono_handle_native_sigsegv + 342
1 mono 0x001c5091 sigabrt_signal_handler + 145
2 libsystem_platform.dylib 0x91d4579b _sigtramp + 43
3 ??? 0xffffffff 0x0 + 4294967295
4 libsystem_c.dylib 0x98fdcc38 abort + 156
5 libsystem_malloc.dylib 0x96e51292 free + 433
6 mono 0x0032b266 mono_error_cleanup + 102
7 mono 0x001a7bda type_commands_internal + 2970
8 mono 0x0019b97d debugger_thread + 5261
9 mono 0x003340ca inner_start_thread + 474
10 libsystem_pthread.dylib 0x96e06780 _pthread_body + 138
11 libsystem_pthread.dylib 0x96e066f6 _pthread_body + 0
12 libsystem_pthread.dylib 0x96e03f7a thread_start + 34
Debug info from gdb:
(lldb) command source -s 0 '/tmp/mono-gdb-commands.TQtGVg'
Executing commands in '/tmp/mono-gdb-commands.TQtGVg'.
(lldb) process attach --pid 10800
Process 10800 stopped
* thread #1: tid = 0x211a96, 0x9386f3ea libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'tid_50b', queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x9386f3ea libsystem_kernel.dylib`__psynch_cvwait + 10
libsystem_kernel.dylib`__psynch_cvwait:
-> 0x9386f3ea <+10>: jae 0x9386f3fa ; <+26>
0x9386f3ec <+12>: calll 0x9386f3f1 ; <+17>
0x9386f3f1 <+17>: popl %edx
0x9386f3f2 <+18>: movl 0xf8cdc2f(%edx), %edx
Executable module set to "/Library/Frameworks/Mono.framework/Versions/4.6.1/bin/mono".
Architecture set to: i386-apple-macosx.
(lldb) thread list
Process 10800 stopped
* thread #1: tid = 0x211a96, 0x9386f3ea libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'tid_50b', queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
thread #2: tid = 0x211a98, 0x9386f3ea libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'SGen worker'
thread #3: tid = 0x211a9a, 0x938684d6 libsystem_kernel.dylib`semaphore_wait_trap + 10, name = 'Finalizer'
thread #4: tid = 0x211a9b, 0x9386fd5e libsystem_kernel.dylib`__workq_kernreturn + 10
thread #5: tid = 0x211a9c, 0x938707fa libsystem_kernel.dylib`kevent_qos + 10, queue = 'com.apple.libdispatch-manager'
thread #6: tid = 0x211a9d, 0x9386fcee libsystem_kernel.dylib`__wait4 + 10, name = 'Debugger agent'
thread #7: tid = 0x211aa1, 0x9386fd5e libsystem_kernel.dylib`__workq_kernreturn + 10
thread #8: tid = 0x211aa5, 0x9386fd5e libsystem_kernel.dylib`__workq_kernreturn + 10
thread #9: tid = 0x211aa8, 0x9386e852 libsystem_kernel.dylib`__accept + 10, name = 'tid_2507'
thread #10: tid = 0x211aa9, 0x9386f646 libsystem_kernel.dylib`__recvfrom + 10, name = 'tid_2b0b'
thread #11: tid = 0x211aaa, 0x9386f3ea libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'tid_330b'
thread #12: tid = 0x211aab, 0x9386f3ea libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'Threadpool worker'
thread #13: tid = 0x211aac, 0x9386f3ea libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'Threadpool worker'
thread #14: tid = 0x211aad, 0x9386f3ea libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'Timer-Scheduler'
thread #15: tid = 0x211aaf, 0x9386f3ea libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'EventPumpThread'
thread #16: tid = 0x211ab0, 0x9386f3ea libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'TestRunnerThread'
(lldb) thread backtrace all
* thread #1: tid = 0x211a96, 0x9386f3ea libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'tid_50b', queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
* frame #0: 0x9386f3ea libsystem_kernel.dylib`__psynch_cvwait + 10
frame #1: 0x96e07538 libsystem_pthread.dylib`_pthread_cond_wait + 757
frame #2: 0x96e09276 libsystem_pthread.dylib`pthread_cond_wait$UNIX2003 + 71
frame #3: 0x0030a955 mono`mono_os_cond_timedwait [inlined] mono_os_cond_wait(cond=0x7a138238, mutex=0x7a13820c) + 12 at mono-os-mutex.h:107 [opt]
frame #4: 0x0030a949 mono`mono_os_cond_timedwait(cond=<unavailable>, mutex=<unavailable>, timeout_ms=<unavailable>) + 185 at mono-os-mutex.h:122 [opt]
frame #5: 0x0030a6cb mono`_wapi_handle_timedwait_signal_handle(handle=0x00001600, timeout=<unavailable>, alertable=<unavailable>, poll=<unavailable>, alerted=0xbff5e390) + 507 at handles.c:1555 [opt]
frame #6: 0x0030a4c8 mono`_wapi_handle_timedwait_signal(timeout=4294967295, poll=0, alerted=0xbff5e23c) + 56 at handles.c:1476 [opt]
frame #7: 0x0031eb5f mono`wapi_WaitForMultipleObjectsEx(numobjects=<unavailable>, handles=<unavailable>, waitall=<unavailable>, timeout=<unavailable>, alertable=<unavailable>) + 1775 at wait.c:620 [opt]
frame #8: 0x002673d4 mono`mono_thread_manage [inlined] wait_for_tids_or_state_change(timeout=4294967295) + 82 at threads.c:3053 [opt]
frame #9: 0x00267382 mono`mono_thread_manage + 322 at threads.c:3258 [opt]
frame #10: 0x00138dc7 mono`mono_main(argc=<unavailable>, argv=<unavailable>) + 8855 at driver.g.c:2187 [opt]
frame #11: 0x000a4141 mono`main [inlined] mono_main_with_options(argc=6, argc=6, argc=6, argv=0xbff5e944, argv=0xbff5e944, argv=0xbff5e944) + 33 at main.c:28 [opt]
frame #12: 0x000a4120 mono`main(argc=6, argv=0xbff5e944) + 1184 at main.c:177 [opt]
frame #13: 0x000a3c75 mono`start + 53
Got a SIGABRT while executing native code. This usually indicates a fatal error in the mono runtime or one of the native libraries used by your application.
I'm working on an xna networked game with lidgren and I can get the client and server to connect, but whenever the client receives a message in the DiscoveryRequest case I get the IndexOutOfRangeException error.
Code for recieving messages in client:
while ((incMsg = client.ReadMessage()) != null)
{
switch (incMsg.MessageType)
{
case NetIncomingMessageType.Data:
Console.WriteLine("recieved message");
break;
case NetIncomingMessageType.DiscoveryRequest:
Console.WriteLine("Connected",incMsg.ReadString());
client.Connect(incMsg.SenderEndpoint);
break;
default:
Console.WriteLine("Unhandled type: " + incMsg.MessageType);
break;
}
client.Recycle(incMsg);
}
Way old question, but for posterity: the DiscoveryRequest does not contain any payload, there is no string to read. It's detailed here: https://code.google.com/p/lidgren-network-gen3/wiki/Discovery
I am writing a multithreaded application where a thread locks the serialport and continuously sends commands and gets responses using SerialPort.Write(command) and SerialPort.ReadLine()
in a loop untill it gets an "OK" response for one particular command.
Is it possible for the thread to switch during a ReadLine() call and cause a TimeOutException.
I have a timeout set at 2000ms.
I have random TmeOutExceptions after the program runs for a few minutes (about 5 - 10)
23332 10:14:23 AM AutoLoader.WinS IRP_MJ_WRITE Serial0 SUCCESS Length 9: STG|4.5..
23336 10:14:23 AM AutoLoader.WinS IRP_MJ_READ Serial0 SUCCESS Length 1: O
23339 10:15:54 AM AutoLoader.WinS IRP_MJ_WRITE Serial0 SUCCESS Length 7: GTSNS..
23342 10:15:54 AM AutoLoader.WinS IRP_MJ_READ Serial0 SUCCESS Length 3: K..
23347 10:15:54 AM AutoLoader.WinS IRP_MJ_WRITE Serial0 SUCCESS Length 7: GLSTS..
23351 10:15:54 AM AutoLoader.WinS IRP_MJ_READ Serial0 SUCCESS Length 1: O
23355 10:15:54 AM AutoLoader.WinS IRP_MJ_READ Serial0 SUCCESS Length 3: K..
After 10:14:23 AM I get a TimeOutException which I suppressed.
while (response != "OK")
{
Thread.Sleep(1000);
_alComm.SendString("SSD|" + CurrentData.MeasuredDepthReturns + Environment.NewLine);
response = _alComm.ReceiveString(2000);
_alComm.SendString("STG|" + CurrentData.AvgGas + Environment.NewLine);
response = _alComm.ReceiveString(2000);
_alComm.SendString("GTSNS\r\n");
response = _alComm.ReceiveString(2000);
SetSamplingTimePercent(response);
}
and
public void SendString(string sDataToSend)
{
if (sDataToSend == "")
return;
try
{
AlPort.Write(sDataToSend);
}
catch (Exception ex)
{
//MessageBox.Show(ex.ToString(), "Error");
}
}
public string ReceiveString(int timeOut)
{
string inString = null;
try
{
// set read timeout
AlPort.ReadTimeout = timeOut;
inString = AlPort.ReadLine();
}
catch (TimeoutException ex)
{
return string.Empty;
}
return inString;
}
A ReadLine (or any I/O for that matter) will cause a context-switch until it is serviced. Now, the way I see there are two possibilities:
Either the thread stays suspended by the OS until the timeout elapses and the exception gets thrown or
You stay suspended until the I/O is serviced at which point with high probability the OS will wake your thread immediately and preempt other threads to allow your code to run. Remember that any modern OS gives a generous priority boost to I/O bound threads.