|
Glad to help
I know you didn't ask for it, but I refactored your snippet into a thread-safe, error handling version as an exercise. I haven't actually run it, but I believe it'll work for you (or at least be close) given that the state object passed as the last parameter to BeginRecieve is _recvState :
private static void ReceiveCallback(IAsyncResult ar)
{
StateObject stateObject = (StateObject)ar.AsyncState;
if (stateObject == null)
{
return;
}
lock (stateObject)
{
if (stateObject.Socket == null)
{
return;
}
int bytesReceived = 0;
try
{
bytesReceived = stateObject.Socket.EndReceive(ar);
}
catch (SocketException)
{
return;
}
catch (ObjectDisposedException)
{
return;
}
if (bytesReceived > 0)
{
SocketConnection.ParseReceiveBuffer(stateObject);
}
stateObject.Socket.BeginReceive(stateObject.DataBuffer, 0, stateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), stateObject);
}
}
public void CloseConnections()
{
lock(_recvState)
{
if (_recvSocket != null)
{
_recvSocket.Shutdown(SocketShutdown.Both);
_recvSocket.Close();
_recvSocket = null;
_recvState.Socket = null;
_recvState = null;
}
}
}
Actually I have to thank you, your original post caused me to go back into some old code and re-look at my own async socket class. Have you ever gone back and looked at something you wrote a long time ago and wondered what was going through your mind when you originally wrote it? I just had one of those moments. It's time for some bug fixing!
|
|
|
|
|
I'm guessing that you have an outstanding call to BeginReceive and calling Close on the Socket . This is probably where you need to research.
I'm also guessing that the reason you're using BeginReceive instead of Receive is because you're running a GUI from this thread and you need to continue to pump messages, right? I've never done this, so I'm not sure what to say. I always try to separate 'View' coding from my 'implementation' coding, so I handle the multithreading like so:
namespace App_Domain
{
class Program
{
static void Main(string[] args)
{
System.Net.Sockets.Socket rec_socket = blah, blah,
send_socket = blah,blah;
System.Threading.Thread rec_pumper = new System.Threading.Thread(
new System.Threading.ParameterizedThreadStart(Pump_Messages));
rec_pumper.Name = "Receive data socket handler";
rec_pumper.Start(rec_socket);
}
public static bool Keep_Running = true;
private const int DATA_LENGTH = 256;
public readonly static Queue<byte[]> _messages = new System.Collections.Generic.Queue<byte[]>();
private static void Pump_Messages(object param)
{
System.Net.Sockets.Socket connected_socket = param as System.Net.Sockets.Socket;
if (connected_socket == null)
throw new System.ArgumentNullException("You must pass a System.Net.Sockets.Socket to me");
byte[] buffer;
while (Keep_Running)
{
if (!connected_socket.Connected)
{
break;
}
if (connected_socket.Available >= DATA_LENGTH)
{
buffer = new byte[DATA_LENGTH];
connected_socket.Receive(buffer);
_messages.Enqueue(buffer);
buffer = null;
}
System.Threading.Thread.Sleep(300);
}
if (connected_socket.Connected)
{
connected_socket.Close();
}
if (Keep_Running)
{
System.Console.WriteLine("Crap! Abnormal termination!! Check the client, he's off his bunker!");
}
}
}
}
I hope this helps.
In Christ,
Aaron Laws
http://ProCure.com
|
|
|
|
|
Thank you for your reply.
You were correct on both of your guesses. I do have an outstanding call to BeginReceive. My problem is that I don't know how to NOT have an outstanding call to BeginReceive. I was under the impression that Socket.Shutdown and Socket.Close were supposed to clear those.
Also, yes I am using this application as a GUI. The form needs to update a DataGrid object fairly constantly in response to socket messages (which is causing a completely different bug that is frustrating me. heh. Am I the only one who misses MFC or Win32 GUI apps? ).
|
|
|
|
|
GrenMeera wrote: You were correct on both of your guesses. I do have an outstanding call to BeginReceive. My problem is that I don't know how to NOT have an outstanding call to BeginReceive. I was under the impression that Socket.Shutdown and Socket.Close were supposed to clear those.
Doesn't really matter. With asynchronous there are two threads and there is no way to insure that an action in thread 1 will only occur at point x in thread 2.
So the close might occur after receiving a message and just as one attempts the reset the BeginReceive.
Mitigation steps can include one or more of the following.
1. Try/catch and experimentation to determine which exceptions are 'normal'
2. A flag that indicates that processing should stop. It should be checked before each action associated with the socket. This flag can also be used to determine the correct handling for exceptions.
3. A message flow that includes a close message - thus BeginReceive would not be reset after this.
|
|
|
|
|
jschell wrote: there is no way to ensure that an action in thread 1 will only occur at point x in thread 2
What do you mean? That's what Monitors, Mutexes, (Manual/Auto)ResetEvents, etc. are for. The other example I posted demonstrates this using lock s. Inside the receive callback the thread waits on the state object until no other thread is in a critical section using the socket. Likewise the Close method waits on the same object until all other threads have left their critical sections that use the socket.
|
|
|
|
|
Dear Sirs,
I'm having a problem with SetWindowsHookEx. In Debug mode, no problem, in release, it throws. Here's the code:
namespace barcode
{
public static class program
{
static void Main(string[] args)
{
_keyboard_delegate = Keyboard_Msg_Pump;
_keyboard_hook_handle = SetWindowsHookEx(
WH_KEYBOARD_LL,
_keyboard_delegate,
System.Runtime.InteropServices.Marshal.GetHINSTANCE(
System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]),
0);
if (_keyboard_hook_handle == 0)
{
int errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(errorCode);
}
}
private static int Keyboard_Msg_Pump(int nCode, System.Int32 wParam, System.IntPtr lParam)
{
return 12;
}
private static int _keyboard_hook_handle;
private static HOOKPROC _keyboard_delegate;
private delegate int HOOKPROC(int nCode, int wParam, System.IntPtr lParam);
private const int WH_KEYBOARD_LL = 13;
[System.Runtime.InteropServices.DllImport("user32.dll",
CharSet=System.Runtime.InteropServices.CharSet.Auto,
CallingConvention=System.Runtime.InteropServices.CallingConvention.StdCall,
SetLastError=true)]
private static extern int SetWindowsHookEx(
int idHook,
HOOKPROC lpfn,
System.IntPtr hMod,
int dwThreadId);
}
}
If you get to line sixteen (right after the if statement in the Main proc), you have an error. Try stepping through this example and tell me if it works for you. If I'm in debug mode, it works for me, but if I'm in release (even with optimize code off, which I thought would make it just like DEBUG), it fails with inconsistent errors, sometimes it says "Operation completed successfully" sometimes it says "Access denied" and other things. Let me know if you can run it in Release, and how. If not, tell me what error you get.
JUST NOW, as I was writing this, I decided that it might be the setting, "Enable the VSHost" process. If it's off, it works. If it's on, no good. Does the VSHost run under lower authority than the user?? Let me know what you think.
In Christ,
Aaron Laws
http://ProCure.com
|
|
|
|
|
Yep, in order for the keyboard hook to work, you have to turn off the VS Hosting process. I don't know why - you just do. I also don't have any documentation on this. I'm just speaking from my own experience.
|
|
|
|
|
Hi , have a good day
Can anyone Explain for me what the meaning of this ?
a = b == null ? null : a.ToString();
P.S : for more information :
I use this component Example Code , and I need to understand it !
http://www.gemboxsoftware.com/help/html/M_GemBox_Spreadsheet_ExcelWorksheet_ExtractToDataTable.htm[^]
if (e.ErrorID == ExtractDataError.WrongType)
{
e.DataTableValue = e.ExcelValue == null ? null : e.ExcelValue.ToString();
e.Action = ExtractDataEventAction.Continue;
}
Please , Don't tell to Ask at Component Forum , due my question is C# syntax things
thank you
I know nothing , I know nothing ...
|
|
|
|
|
It means
if (b == null)
a = null;
else
a = a.ToString();
But it's an expression instead of a statement.
|
|
|
|
|
Thank you so much , for this fast , great replay of yours ,
you saved me from headache
I have voted for you
I know nothing , I know nothing ...
|
|
|
|
|
Thanks
|
|
|
|
|
And yes I meant b.toString();
I know nothing , I know nothing ...
|
|
|
|
|
everything you should know about C# is in your C# book, in MSDN, in the C# specification[^], etc.
|
|
|
|
|
Thank you ,
But for a certain things MSDN is Yak !
http://msdn.microsoft.com/en-us/library/ty67wk28.aspx[^]
The conditional operator is right-associative. The expression a ? b : c ? d : e is evaluated as a ? b : (c ? d : e), not as (a ? b : c) ? d : e.<br />
<br />
The conditional operator cannot be overloaded.
I know nothing , I know nothing ...
|
|
|
|
|
You're right, and that's classic Microsoft - technically accurate, entirely useless information!
"A Journey of a Thousand Rest Stops Begins with a Single Movement"
|
|
|
|
|
"you're in an airplane" kind of stuff?
|
|
|
|
|
Exactly!
"A Journey of a Thousand Rest Stops Begins with a Single Movement"
|
|
|
|
|
Where is the Yak point? In all fairness, the first line of the document states;
The conditional operator (?:) returns one of two values depending on the value of a Boolean expression.
Perfect logical KISS.
I are Troll
|
|
|
|
|
I do not understand why you think like that.
|
|
|
|
|
I guess you meant b.ToString there. If you did, you really don't need ternary operator. Convert.ToString would be enough.
|
|
|
|
|
a = b == null ? null : a.ToString();
Means if b equals null then set a = null
else set a = a.ToString()
if code changed to following, I may understand it.
if (b == null)
{
a = null;
}
else
{
a = a.toString()
}
|
|
|
|
|
? operator its like a IF-result statement.
look:
int x = 0;
int y = 1;
if(x > y) ? y++ : y--;
If x>y = true, y++.
If x>y = false, y--;
|
|
|
|
|
I am using FFMPEG for streaming operations.
(https://www.transferbigfiles.com/a3209f95-ffcc-4c82-b722-041a24c26ec1?rid=KsWHbP3Lo/rxGH4YHVVVtA%3d%3d)
I started it using the following program
Process myProcess = new Process();
myProcess.StartInfo.FileName = @"ffmpeg.exe";
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.Arguments = "-i input.avi -vcodec copy -acodec copy output.avi";
myProcess.Start();
StreamWriter myStreamWriter = myProcess.StandardInput;
myStreamWriter.Write("113");
myStreamWriter.Flush();
myStreamWriter.Write('q');
myStreamWriter.Flush();
myStreamWriter.Close();
myProcess.WaitForExit();
myProcess.Close();
My intention is to close the program when I send "q" from the program (I meant a graceful exit without making any error).
But I can't close it by sending 'q' character or its corresponding ascii. When I run the program from the command line and I press q in the keyboard, program immediately gets closed.
Can you pls. help me?
Thank you
regards
anvesh
|
|
|
|
|
|
Thanx for the reply,
Its actually a nice article. But I couldn't solve my issue using it.
A carriage return is not necessary for this application to close. Pressing a 'q' itself (from keyboard) will give give graceful end to the program. I need not press an additional enter key.
And as an additional step of precaution, I made my own console program which requries a 'q' followed by carriage return to close the application, and it worked fine when I use WriteLine from .NET
What might be the issue? Its only for ffmpeg that I can't send input stream to. I am anxious to know what might be the issue?
|
|
|
|