从C#中的小文件传输套接字应用程序开始(目前主要是MS示例代码)。使用ManualResetEvent.WaitOne()时遇到问题。我在 foreach循环中调用它,所以也许这就是问题所在 在任何情况下,我都试图命令/阻止BeginSend调用,以便在成功文件传输后启动。但似乎即使我在每次BeginSend之后调用WaitOne(),它们也会出现故障。
以下是一个示例:
public class AsynchronousClient {
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
private static ManualResetEvent sendDone =
new ManualResetEvent(false);
private static ManualResetEvent receiveDone =
new ManualResetEvent(false);
...
private static void SendAll(Socket client, String path)
{
String[] files = GetFiles(path);
int i = 0;
foreach(String file in files){
Console.WriteLine("STEP 1 - Files left: {0}", files.Length - i);
SendFile(client, Path.GetFullPath(file), files.Length - i);
sendDone.WaitOne();
i++;
}
}
private static void SendFile(Socket client, String path, int FilesLeft )
{
byte[] filesLeft = BitConverter.GetBytes((Int64)FilesLeft);
byte[] fileData = File.ReadAllBytes(path);
byte[] fileLength = BitConverter.GetBytes((Int64) fileData.Length);
byte[] fileMD5;
using (MD5 md5Hash = MD5.Create())
{
fileMD5 = md5Hash.ComputeHash(fileData);
}
byte[] filepathdata = Encoding.Unicode.GetBytes(path);
byte[] filepathLength = BitConverter.GetBytes((Int16)filepathdata.Length);
byte[] byteData = filesLeft.Concat(fileLength).Concat(fileMD5).Concat(filepathLength).Concat(filepathdata).Concat(fileData).ToArray();
Console.WriteLine("STEP 2 - File length: {0}", fileData.Length);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("STEP 3 - Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
...这里是步骤的顺序:
STEP 1 - Files left: 16
STEP 2 - File length: 432759
STEP 3 - Sent 433033 bytes to server.
STEP 1 - Files left: 15
STEP 2 - File length: 262623
STEP 1 - Files left: 14
STEP 3 - Sent 262897 bytes to server.
STEP 2 - File length: 459683
STEP 1 - Files left: 13
STEP 2 - File length: 369381
STEP 1 - Files left: 12
STEP 2 - File length: 271126
STEP 1 - Files left: 11
STEP 3 - Sent 459957 bytes to server.
STEP 3 - Sent 369679 bytes to server.
STEP 2 - File length: 1647983
STEP 1 - Files left: 10
STEP 2 - File length: 24761
STEP 1 - Files left: 9
STEP 3 - Sent 25049 bytes to server.
STEP 3 - Sent 271424 bytes to server.
STEP 2 - File length: 858717
STEP 1 - Files left: 8
STEP 2 - File length: 214031
STEP 1 - Files left: 7
STEP 2 - File length: 531963
STEP 1 - Files left: 6
STEP 2 - File length: 227950
STEP 1 - Files left: 5
STEP 2 - File length: 394068
STEP 1 - Files left: 4
STEP 2 - File length: 243546
STEP 1 - Files left: 3
STEP 2 - File length: 173656
STEP 1 - Files left: 2
STEP 2 - File length: 712417
STEP 1 - Files left: 1
STEP 3 - Sent 1648279 bytes to server.
STEP 2 - File length: 1631924
STEP 3 - Sent 859001 bytes to server.
STEP 3 - Sent 214309 bytes to server.
STEP 3 - Sent 532239 bytes to server.
STEP 3 - Sent 228226 bytes to server.
STEP 3 - Sent 394346 bytes to server.
STEP 3 - Sent 243822 bytes to server.
STEP 3 - Sent 173936 bytes to server.
STEP 3 - Sent 712701 bytes to server.
STEP 3 - Sent 1632220 bytes to server.
ReceiveCallback: bytesRead <= 0
Response received : OK
问题是:即使步骤乱序,文件数据在服务器端也完好无损。看起来在它完成之前多次调用BeginSend是可行的,但我仍然可以选择在开始另一次传输之前等待文件进入服务器。
答案 0 :(得分:0)
如果可以,您应该考虑使用Web服务。在客户端/服务器之间双向发送/流式传输文件都有很好的嵌入式功能。
答案 1 :(得分:0)
ManualResetEvent
的行为与名称告诉我们完全相同:必须手动重置!
手动重置事件就像门。当事件未发出信号时,等待它的线程将阻塞。当发出事件信号时,释放所有等待线程,并且在调用其Reset方法之前,事件保持信号通知(即,后续等待不会阻塞)。当一个线程必须在其他线程可以继续之前完成一个活动时,手动重置事件很有用。
自动重置事件提供对资源的独占访问。如果在没有线程等待时发出自动重置事件的信号,它将保持信号状态,直到线程尝试等待它。该事件释放线程并立即重置,阻塞后续线程。
(资料来源:http://msdn.microsoft.com/en-us/library/system.threading.eventwaithandle.aspx)
出于您的目的,AutoResetEvent
应该适合。
进一步消耗:
在您的示例中,它等待第一个Set()
,然后门打开,所有以下WaitOne()
只能在没有人关闭门时通过。