Я создаю приложение Silverlight, которое использует реализацию H.264 MediaStreamSource для потоковой передачи видео в реальном времени с сервера. У меня есть созданный мной стример Multipart, который считывает образцы кадр за кадром.
Когда я подключаюсь к серверу, работающему на моем локальном компьютере, требуется 12 секунд, чтобы прочитать второй байт из потока ответа в функции ReadHeaders (). Таким образом, в основном он мгновенно подключается к хосту, успешно считывает один байт, последующие блоки ReadByte () (если вы посмотрите, где находится стек вызовов, он находится в другом потоке: System.Windows.dll! MS.Internal.InternalNetworkStream.ReadOperation (состояние объекта)). Каждый раз, когда я это проверяю, это занимает 12 секунд. По прошествии этого времени все последующие чтения выполняются немедленно, и приложение отлично работает. Если я использую этот же код в простом консольном приложении .NET, задержки в 12 секунд не будет.
Есть идеи, что могло быть причиной этого?
byte[] imgBuf = new byte[ChunkSize * ChunkSize];
HttpWebRequest req = (HttpWebRequest)res.AsyncState;
int contentLength = 0;
try
{
HttpWebResponse resp = (HttpWebResponse)req.EndGetResponse(res);
// notify delegate of main headers
// get the response stream and start reading
BinaryReader reader = new BinaryReader(resp.GetResponseStream());
Dictionary<string, string> headers;
while (m_Running)
{
// read multipart response headers and notify delegate
headers = ReadHeaders(reader);
// check if end of stream
if (headers.ContainsKey(CustomHeaders.EndOfStreamHeader)
&& headers[CustomHeaders.EndOfStreamHeader] != null
&& String.Compare(headers[CustomHeaders.EndOfStreamHeader], "yes") == 0)
{
// notify delegate if end of stream has been reached
}
// determine length of data to read
string cl = headers["Content-Length"];
if (cl != null)
{
contentLength = Int32.Parse(cl);
}
byte[] data = reader.ReadBytes(contentLength);
if (data.Length > 0)
{
// notify delegate of multipart data
}
// Yield to other threads waiting to be executed
System.Threading.Thread.Sleep(1);
}
reader.Close();
resp.Close();
req.Abort();
}
catch (Exception ex)
{
// notify delegate of any errors that occurred
}
Функция ReadHeaders ():
private Dictionary<string, string> ReadHeaders(BinaryReader reader)
{
List<byte> buffer = new List<byte>();
while (m_Running)
{
buffer.Add(reader.ReadByte());
if (buffer.EndsWith(EndOfHeaderBytes))
{
break;
}
// Yield to other threads waiting to be executed
System.Threading.Thread.Sleep(1);
}
return buffer.ToHeadersDictionary();
}
Изменить: вот стек вызовов двух потоков.
Unflagged 5096 5 Рабочий поток Рабочий поток [В спящем режиме, ожидании или присоединении] Нормальный [В спящем режиме, ожидании или присоединении]
mscorlib.dll! System.Threading.WaitHandle.InternalWaitOne (System.Runtime.InteropServices.SafeHandle waitableSafeHandle, long millisecondsTimeout, bool hasThreadAffinity, bool exitContext) + 0x21 байт
mscorlib.dll! System.Threading.WaitHandle.WaitOne (long timeout, bool exitContext) + 0x21 байт
mscorlible.dll! System.Threading. .WaitOne (int millisecondsTimeout, bool exitContext) + 0x1f байт
mscorlib.dll! System.Threading.WaitHandle.WaitOne () + 0x10 байт
System.Windows.dll! MS.Internal.InternalNetworkStream.ReadOperation (состояние объекта ) + 0x8a байтов
mscorlib.dll! System.Threading.QueueUserWorkItemCallback.WaitCallback_Context (состояние объекта) + 0x3e байтов
mscorlib.dll! System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, обратный вызов System.Threading.ContextCallback, состояние объекта, bool preserveSyncCtx) + 0x97 байт
mscorlib.dll! System.Threading.QueueUserWorkItem. Threading.IThreadPoolWorkItem.ExecuteWorkItem () + 0x5a байтов
mscorlib.dll! System.Threading.ThreadPoolWorkQueue.Dispatch () + 0x1b3 байтов
mscorlib.dll! > [Переход от собственного к управляемому]
[Переход домена приложения]
[Переход от собственного к управляемому]
Отсюда трудно увидеть настоящую причину, но это может быть что-то связанное с управлением потоками. Первый подозреваемый, которого я здесь вижу, -
byte[] imgBuf = new byte[ChunkSize * ChunkSize];
HttpWebRequest req = (HttpWebRequest)res.AsyncState;
int contentLength = 0;
try
{
HttpWebResponse resp = (HttpWebResponse)req.EndGetResponse(res);
// notify delegate of main headers
// get the response stream and start reading
BinaryReader reader = new BinaryReader(resp.GetResponseStream());
Dictionary<string, string> headers;
while (m_Running)
{
// read multipart response headers and notify delegate
headers = ReadHeaders(reader);
// check if end of stream
if (headers.ContainsKey(CustomHeaders.EndOfStreamHeader)
&& headers[CustomHeaders.EndOfStreamHeader] != null
&& String.Compare(headers[CustomHeaders.EndOfStreamHeader], "yes") == 0)
{
// notify delegate if end of stream has been reached
}
// determine length of data to read
string cl = headers["Content-Length"];
if (cl != null)
{
contentLength = Int32.Parse(cl);
}
byte[] data = reader.ReadBytes(contentLength);
if (data.Length > 0)
{
// notify delegate of multipart data
}
// Yield to other threads waiting to be executed
System.Threading.Thread.Sleep(1);
}
reader.Close();
resp.Close();
req.Abort();
}
catch (Exception ex)
{
// notify delegate of any errors that occurred
}
. Сосредоточьтесь на этом. Возможно, некоторые элементы потоковой передачи различаются для разных типов проектов.