I've been banging my head against this issue for at least a week now (learned something new too - WCF is a major PITA).
Here's my problem: I have a scenario in my app that at some point freezes the whole client for, like, forever (because I disabled the timeouts, as both the client and server are in a controlled environment). The deadlock happens exactly on the same call, I presume due to the burst of requests preceding it.
Inspecting the deadlock stack trace on the client gives me this:
[In a sleep, wait, or join]
WindowsBase.dll!System.Windows.Threading.DispatcherSynchronizationContext.Wait(System.IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) + 0x26 bytes
mscorlib.dll!System.Threading.SynchronizationContext.InvokeWaitMethodHelper(System.Threading.SynchronizationContext syncContext, System.IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) + 0x1c bytes
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle waitableSafeHandle, long millisecondsTimeout, bool hasThreadAffinity, bool exitContext) + 0x2b bytes
mscorlib.dll!System.Threading.WaitHandle.WaitOne(int millisecondsTimeout, bool exitContext) + 0x2d bytes
mscorlib.dll!System.Threading.WaitHandle.WaitOne() + 0x10 bytes
System.Runtime.DurableInstancing.dll!System.Runtime.TimeoutHelper.WaitOne(System.Threading.WaitHandle waitHandle, System.TimeSpan timeout) + 0x7c bytes
System.ServiceModel.dll!System.ServiceModel.Channels.OverlappedContext.WaitForSyncOperation(System.TimeSpan timeout, ref object holder) + 0x40 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.PipeConnection.WaitForSyncRead(System.TimeSpan timeout, bool traceExceptionsAsErrors) + 0x38 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.PipeConnection.Read(byte[] buffer, int offset, int size, System.TimeSpan timeout) + 0xef bytes
System.ServiceModel.dll!System.ServiceModel.Channels.DelegatingConnection.Read(byte[] buffer, int offset, int size, System.TimeSpan timeout) + 0x21 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ConnectionUpgradeHelper.InitiateUpgrade(System.ServiceModel.Channels.StreamUpgradeInitiator upgradeInitiator, ref System.ServiceModel.Channels.IConnection connection, System.ServiceModel.Channels.ClientFramingDecoder decoder, System.ServiceModel.IDefaultCommunicationTimeouts defaultTimeouts, ref System.Runtime.TimeoutHelper timeoutHelper) + 0xb3 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.SendPreamble(System.ServiceModel.Channels.IConnection connection, System.ArraySegment<byte> preamble, ref System.Runtime.TimeoutHelper timeoutHelper) + 0x155 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.DuplexConnectionPoolHelper.AcceptPooledConnection(System.ServiceModel.Channels.IConnection connection, ref System.Runtime.TimeoutHelper timeoutHelper) + 0x25 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ConnectionPoolHelper.EstablishConnection(System.TimeSpan timeout) + 0xe2 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.OnOpen(System.TimeSpan timeout) + 0x37 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.CommunicationObject.Open(System.TimeSpan timeout) + 0x13f bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannel.OnOpen(System.TimeSpan timeout) + 0x52 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.CommunicationObject.Open(System.TimeSpan timeout) + 0x13f bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(System.ServiceModel.Channels.ServiceChannel channel, System.TimeSpan timeout) + 0x12 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(System.TimeSpan timeout, System.ServiceModel.Channels.ServiceChannel.CallOnceManager cascade) + 0x10c bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannel.Call(string action, bool oneway, System.ServiceModel.Dispatcher.ProxyOperationRuntime operation, object[] ins, object[] outs, System.TimeSpan timeout) + 0x18b bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(System.Runtime.Remoting.Messaging.IMethodCallMessage methodCall, System.ServiceModel.Dispatcher.ProxyOperationRuntime operation) + 0x59 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannelProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage message) + 0x65 bytes
mscorlib.dll!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(ref System.Runtime.Remoting.Proxies.MessageData msgData, int type) + 0xee bytes
MyService.dll!MyService.Controller.CallMethod() + 0x9 bytes
The reason I suspect the bursting calls sequence is that if I insert a sleep of 60s before the call is made, the deadlock doesn't occur.
Does anybody have any suggestion on how to avoid this issue?
P.S. I'm using named pipes.
EDIT:
The call to the WCF service on the client side happens on the GUI thread. Am I right to assume (from the callstack) that it tries to access the GUI thread, which is causing the deadlock?
EDIT:
Client side channel factory initialization:
var binding = new NetNamedPipeBinding
{
OpenTimeout = TimeSpan.MaxValue,
CloseTimeout = TimeSpan.MaxValue,
SendTimeout = TimeSpan.MaxValue,
ReceiveTimeout = TimeSpan.MaxValue,
ReaderQuotas = { MaxStringContentLength = Int32.MaxValue, MaxArrayLength = Int32.MaxValue },
MaxBufferPoolSize = Int32.MaxValue,
MaxBufferSize = Int32.MaxValue,
MaxReceivedMessageSize = Int32.MaxValue
};
CustomBinding pipeBinding = new CustomBinding(binding);
pipeBinding.Elements.Find<NamedPipeTransportBindingElement>().ConnectionPoolSettings.IdleTimeout = TimeSpan.FromDays(24);
channelFactory = new ChannelFactory<ITestsModule>(pipeBinding,
new EndpointAddress(string.Format("net.pipe://localhost/app_{0}/TestsModule", ProcessId)));
Server side host initialization:
var host = new ServiceHost(m_testModule, new Uri[] { new Uri(string.Format("net.pipe://localhost/app_{0}", Process.GetCurrentProcess().Id)) });
ServiceThrottlingBehavior throttle = host.Description.Behaviors.Find<ServiceThrottlingBehavior>();
if (throttle == null)
{
throttle = new ServiceThrottlingBehavior();
throttle.MaxConcurrentCalls = 500;
throttle.MaxConcurrentSessions = 200;
throttle.MaxConcurrentInstances = 100;
host.Description.Behaviors.Add(throttle);
}
ThreadPool.SetMinThreads(1000, 1000);
var binding = new NetNamedPipeBinding
{
OpenTimeout = TimeSpan.MaxValue,
CloseTimeout = TimeSpan.MaxValue,
SendTimeout = TimeSpan.MaxValue,
ReceiveTimeout = TimeSpan.MaxValue,
ReaderQuotas = { MaxStringContentLength = Int32.MaxValue, MaxArrayLength = Int32.MaxValue },
MaxBufferPoolSize = Int32.MaxValue,
MaxBufferSize = Int32.MaxValue,
MaxReceivedMessageSize = Int32.MaxValue
};
CustomBinding pipeBinding = new CustomBinding(binding);
pipeBinding.Elements.Find<NamedPipeTransportBindingElement>().ConnectionPoolSettings.IdleTimeout = TimeSpan.FromDays(24);
host.AddServiceEndpoint(typeof(ITestsModule), pipeBinding, "TestsModule");
Service class behavior:
[ServiceBehavior(
InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple,
UseSynchronizationContext = false,
IncludeExceptionDetailInFaults = true
)]
First, you know what you're locking on server side? Is lock contention coming only from WCF interface? Or your server also locking from other components/classes elsewhere? That's the most important question and it has nothing to do with WCF.
Now, this said, try this to help narrow down the issue:
OPTION 1:
Timeout's on client side - don't set to Int32.MaxValue, set to say ten seconds, and implement client side re-try on timeout's.
OPTION 2:
ServiceThrottlingBehavior ThrottleBehavior = new ServiceThrottlingBehavior();
ThrottleBehavior.MaxConcurrentSessions = 4;
ThrottleBehavior.MaxConcurrentCalls = 4;
ThrottleBehavior.MaxConcurrentInstances = 4;
ServiceHost Host = ...
Host.Description.Behaviors.Add(ThrottleBehavior);
If OPTION 2 helps, stress test it (well should do same with OPTION 1)- also watch out for build up of thread counts if MaxConcurrentXXX set to a big number.
Hope this helps
Related
I'm using Apache Mina framework for communication between server and client, when I test the programe, I found if my transmission frequency is too fast, the received packets will merge to a big one, which should be each separate package.
My client used to send message, code like below:
public static void main(String[] args) {
// IoConnector instance
IoConnector connector = new NioSocketConnector();
connector.setConnectTimeoutMillis(3000); // 连接超时时间
// configure filters
// connector.getFilterChain().addLast("coderc", new ProtocolCodecFilter(
// new TextLineCodecFactory(Charset.forName("UTF-8"))));
DefaultIoFilterChainBuilder builder = (DefaultIoFilterChainBuilder) connector.getFilterChainBuilder();
Map<String, IoFilter> filters = new LinkedHashMap<>();
filters.put("protocolCodecFilter", new ProtocolCodecFilter(new TcpCodecFactory()));
filters.put("executor", new ExecutorFilter());
filters.put("loggingFilter", new LoggingFilter());
builder.setFilters(filters);
connector.setFilterChainBuilder(builder);
// set handler
connector.setHandler(new TcpServerHandler());
// connect to the server
ConnectFuture future = connector.connect(new InetSocketAddress(address, port));
future.awaitUninterruptibly(); // waiting for connection
IoSession session = future.getSession();
byte[] data = new byte[10];
for (int i = 0; i < 100; ++i) {
data[0] = (byte)i; // first byte means the message sequence number
for (int j = 1; j < 10; ++j) {
data[j] = (byte) (j + 10);
}
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
session.write(data);
}
session.getCloseFuture().awaitUninterruptibly(); // wait for close
connector.dispose();
}
When I comment the sleep code, which means I send message frequently, My received message will like below:
The message sequence number is 0, 1, 6..., If I uncomment the sleep code, the message sequence number is 0, 1, 2, 3...
What's the difference? How to avoid the mixed packets in fast transmission?
You are using a TCP socket which is a stream channel versus UDP which is a message channel. Your messages are being combined because that is how TCP works on all platforms to effectively create as few network packets as possible.
Unless the messages are out of order, then this is the expected behavior.
This is my CoAP Client code for sending requests with incremental payload size:
CoapClient client = new CoapClient(uri);
for (int payloadSize = start; payloadSize <= end; payloadSize += stepSize) {
for (int repeatCount = 0; repeatCount < repeatNo; repeatCount++) {
//building payload
StringBuilder sb = new StringBuilder();
for (int i = 0; i< payloadSize ; i ++)
sb.append("a");
//building request with payload
Request req = new Request(CoAP.Code.GET);
req.setPayload(sb.toString().getBytes());
//sending request
long sendTime = System.currentTimeMillis();
CoapResponse response = client.advanced(req);
long receiveTime = System.currentTimeMillis();
long transmissionTime = receiveTime - sendTime;
...
But, it seems UDP Datagram fragmantation or CoAP block-wise transfer is not happening for the client. What am I doing wrong?
In my local machine, the max payload transferred is about 2300 (less than 2400) bytes. and over internet is about 1400 (less than 1500).
I want to send big requests from the CoAP client to CoAP server. What am I doing wrong? (Specifically to Californium CoAP implementation please.)
Thanks.
I'm struggling with the below exception using WaveFileWriter. This exception occurs intermittently -- most times this works fine. Code snippet below:
MemoryStream s = new MemoryStream();
MemoryStream newStream = new MemoryStream();
int length = 0;
byte[] buffer = null;
int read = 0;
MixingSampleProvider mixer2 = new MixingSampleProvider(_samples);
SampleToWaveProvider16 mixer3 = new SampleToWaveProvider16(mixer2);
length = mixer3.WaveFormat.AverageBytesPerSecond*Convert.ToInt32(position.TotalSeconds); //position is a Timespan calculated to be the total duration of the WAV files
buffer = new byte[length];
WaveFileWriter waveFileWriter = new WaveFileWriter(new IgnoreDisposeStream(s), mixer3.WaveFormat);
while ((read = mixer3.Read(buffer, 0, buffer.Length)) > 0)
{
waveFileWriter.Write(buffer, 0, read);
}
waveFileWriter.Flush();
waveFileWriter.Close();
waveFileWriter.Dispose();
s.WriteTo(newStream);
Here are the details of the Exception:
System.IndexOutOfRangeException was caught
HResult=-2146233080
Message=Index was outside the bounds of the array.
Source=NAudio
StackTrace:
at NAudio.Wave.SampleProviders.Pcm16BitToSampleProvider.Read(Single[] buffer, Int32 offset, Int32 count)
at NAudio.Wave.SampleProviders.OffsetSampleProvider.Read(Single[] buffer, Int32 offset, Int32 count)
at NAudio.Wave.SampleProviders.MixingSampleProvider.Read(Single[] buffer, Int32 offset, Int32 count)
at NAudio.Wave.SampleProviders.OffsetSampleProvider.Read(Single[] buffer, Int32 offset, Int32 count)
at NAudio.Wave.SampleProviders.MixingSampleProvider.Read(Single[] buffer, Int32 offset, Int32 count)
at NAudio.Wave.SampleProviders.SampleToWaveProvider16.Read(Byte[] destBuffer, Int32 offset, Int32 numBytes)
at GamedayRadio.HalfInning.Process() in xxxxxx
InnerException:
Not sure if this is causing your error, but do make sure that the read length is an exact multiple of the BlockAlign for your WaveFormat. So for example when reading stereo 16 bit audio, always read multiples of 4 bytes (2 channels x 2 bytes per sample). Your buffer looks like it might be an odd number of bytes in some circumstances
For a project, I want to get the list of all free/used clusters on an NTFS partition.
For this i have to dump the $Bitmap file and parse its contents.
There are few API's and examples on the web, but however they don't seem to work. Is there a simple way/ code sample to just copy the $Bitmap file somewhere.
Is using FSCTL_GET_VOLUME_BITMAP the only way? Ideally I would like to do it in C#.
NFI.EXE which is (used to be) part of the "oem support tools" can enumerate all NTFS partition items. It might also be capable to dump the content of $Bitmap.
You definitely want to go the easy route and use the IOCTL rather than trying to read $Bitmap directly. Of course, you don't have to do it yourself if somebody has done it for you. It turns out that an MSDN blogger has already written a nice little wrapper for you:
http://blogs.msdn.com/jeffrey_wall/archive/2004/09/13/229137.aspx
The whole class is over 300 lines of code, so I won't post it all, but here's the function that gets the volume bitmap:
/// <summary>
/// Get cluster usage for a device
/// </summary>
/// <param name="DeviceName">use "c:"</param>
/// <returns>a bitarray for each cluster</returns>
static public BitArray GetVolumeMap(string DeviceName)
{
IntPtr pAlloc = IntPtr.Zero;
IntPtr hDevice = IntPtr.Zero;
try
{
hDevice = OpenVolume(DeviceName);
Int64 i64 = 0;
GCHandle handle = GCHandle.Alloc(i64, GCHandleType.Pinned);
IntPtr p = handle.AddrOfPinnedObject();
// alloc off more than enough for my machine
// 64 megs == 67108864 bytes == 536870912 bits == cluster count
// NTFS 4k clusters == 2147483648 k of storage == 2097152 megs == 2048 gig disk storage
uint q = 1024 * 1024 * 64; // 1024 bytes == 1k * 1024 == 1 meg * 64 == 64 megs
uint size = 0;
pAlloc = Marshal.AllocHGlobal((int)q);
IntPtr pDest = pAlloc;
bool fResult = DeviceIoControl(
hDevice,
FSConstants.FSCTL_GET_VOLUME_BITMAP,
p,
(uint)Marshal.SizeOf(i64),
pDest,
q,
ref size,
IntPtr.Zero);
if (!fResult)
{
throw new Exception(Marshal.GetLastWin32Error().ToString());
}
handle.Free();
/*
object returned was...
typedef struct
{
LARGE_INTEGER StartingLcn;
LARGE_INTEGER BitmapSize;
BYTE Buffer[1];
} VOLUME_BITMAP_BUFFER, *PVOLUME_BITMAP_BUFFER;
*/
Int64 StartingLcn = (Int64)Marshal.PtrToStructure(pDest, typeof(Int64));
Debug.Assert(StartingLcn == 0);
pDest = (IntPtr)((Int64)pDest + 8);
Int64 BitmapSize = (Int64)Marshal.PtrToStructure(pDest, typeof(Int64));
Int32 byteSize = (int)(BitmapSize / 8);
byteSize++; // round up - even with no remainder
IntPtr BitmapBegin = (IntPtr)((Int64)pDest + 8);
byte[] byteArr = new byte[byteSize];
Marshal.Copy(BitmapBegin, byteArr, 0, (Int32)byteSize);
BitArray retVal = new BitArray(byteArr);
retVal.Length = (int)BitmapSize; // truncate to exact cluster count
return retVal;
}
finally
{
CloseHandle(hDevice);
hDevice = IntPtr.Zero;
Marshal.FreeHGlobal(pAlloc);
pAlloc = IntPtr.Zero;
}
}
I'm trying to implement SQL CE in a WP7 Mango project, but now I'm encountering this error when I try to insert/save an object to my DB.
My code below:
public static void Save(MyObject myobject)
{
using (DBDataContext dc = new DBDataContext(DBDataContext.ConnectionString))
{
dc.MyObject.InsertOnSubmit(myobject);
dc.SubmitChanges();
}
}
When code hits the insertonsubmit line, it breaks with
MissingMethodException was unhandled
MissingMethodException
And that's all it tells me.
Call stack:
mscorlib.dll!System.Activator.InternalCreateInstance(System.Type type, bool nonPublic, ref System.Threading.StackCrawlMark stackMark) + 0xe4 bytes
mscorlib.dll!System.Activator.CreateInstance(System.Type type) + 0x2 bytes
System.Data.Linq.dll!System.Data.Linq.WorkAround.ActivationHelper.CreateInstance(System.Type type)
System.Data.Linq.dll!System.Data.Linq.ChangeTracker.StandardChangeTracker.StandardTrackedObject.CreateDataCopy(object instance) + 0x12 bytes
System.Data.Linq.dll!System.Data.Linq.ChangeTracker.StandardChangeTracker.StandardTrackedObject.StartTracking() + 0x16 bytes
System.Data.Linq.dll!System.Data.Linq.ChangeTracker.StandardChangeTracker.OnPropertyChanging(object sender, System.ComponentModel.PropertyChangingEventArgs args) + 0x16 bytes
System.Data.Linq.dll!System.Data.Linq.ChangeTracker.StandardChangeTracker.Attach(object obj) + 0x1f bytes
System.Data.Linq.dll!System.Data.Linq.ChangeTracker.StandardChangeTracker.Track(System.Data.Linq.Mapping.MetaType mt, object obj, System.Collections.Generic.Dictionary<object,object> visited, bool recurse, int level) + 0x4e bytes
System.Data.Linq.dll!System.Data.Linq.ChangeTracker.StandardChangeTracker.Track(object obj, bool recurse) + 0x1d bytes
System.Data.Linq.dll!System.Data.Linq.ChangeTracker.StandardChangeTracker.Track(object obj) + 0x3 bytes
System.Data.Linq.dll!System.Data.Linq.Table<FotoDok.EkstraFeltMulighed>.InsertOnSubmit(FotoDok.EkstraFeltMulighed entity) + 0xac bytes
FotoDok.dll!FotoDok.EkstraFeltMulighed.Gem(FotoDok.EkstraFeltMulighed ekstrafeltmulighed) Line 70 + 0xc bytes C#
FotoDok.dll!FotoDok.opdaterProjekter.behandlProjektJson(Newtonsoft.Json.Linq.JObject o) Line 202 + 0x7 bytes C#
FotoDok.dll!FotoDok.opdaterProjekter.ReadCallbackValgteProjekter.AnonymousMethod__1(System.Windows.Controls.CheckBox delChk, Newtonsoft.Json.Linq.JObject delO) Line 141 + 0x7 bytes C#
mscorlib.dll!System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo rtmi, object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object parameters, System.Globalization.CultureInfo culture, bool isBinderDefault, System.Reflection.Assembly caller, bool verifyAccess, ref System.Threading.StackCrawlMark stackMark)
mscorlib.dll!System.Reflection.RuntimeMethodInfo.InternalInvoke(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture, ref System.Threading.StackCrawlMark stackMark) + 0x168 bytes
mscorlib.dll!System.Reflection.MethodBase.Invoke(object obj, object[] parameters) + 0xa bytes
mscorlib.dll!System.Delegate.DynamicInvokeOne(object[] args) + 0x98 bytes
mscorlib.dll!System.MulticastDelegate.DynamicInvokeImpl(object[] args) + 0x8 bytes
mscorlib.dll!System.Delegate.DynamicInvoke(object[] args) + 0x2 bytes
System.Windows.dll!System.Windows.Threading.DispatcherOperation.Invoke() + 0xc bytes
System.Windows.dll!System.Windows.Threading.Dispatcher.Dispatch(System.Windows.Threading.DispatcherPriority priority) + 0x83 bytes
System.Windows.dll!System.Windows.Threading.Dispatcher.OnInvoke(object context) + 0x8 bytes
System.Windows.dll!System.Windows.Hosting.CallbackCookie.Invoke(object[] args) + 0x19 bytes
System.Windows.dll!System.Windows.Hosting.DelegateWrapper.InternalInvoke(object[] args) + 0x2 bytes
System.Windows.RuntimeHost.dll!System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(System.IntPtr pHandle, int nParamCount, System.Windows.Hosting.NativeMethods.ScriptParam[] pParams, ref System.Windows.Hosting.NativeMethods.ScriptParam pResult) + 0x5e bytes
[External Code]
I've managed to insert other objects, using the same approach just fine, but I can't figure out what makes this object any different.
I solved it myself, googling even more about it (Typical, searching for hours, then right after making a post here I stumble on an answer..)
Aparrently my classes must have an empty contructor, if they don't the error appears.
So adding empty constructors to my classes solved it.
I would like to add that the constructor must be public. I have the same problem, but in my model class I had empty internal constructor.