Я создаю приложение Silverlight, которое использует реализацию H.264 MediaStreamSource для потокового видео в реальном времени с сервера. У меня есть стример Multipart, который я написал, который читает образцы по кадре.Silverlight HttpWebRequest BinaryReader вторая операция чтения всегда занимает много времени (12 секунд)
Когда я подключаюсь к серверу, работающему на моем локальном компьютере, для чтения второго байта из потока ответов в функции ReadHeaders() требуется 12 секунд. Таким образом, в основном он мгновенно подключается к хосту, быстро читает один байт, последующие блоки 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();
}
Edit: Вот стек вызовов из двух потоков.
работник темы GenIIIWebClient.CVRESTLib.HttpMultipartStreamer.ReadHeaders работник темы Нормальный [во сне, ждать, или присоединиться к]
mscorlib.dll! System.Threading.WaitHandle.InternalWaitOne (System.Runtime.InteropServices.SafeHandle waitableSafeHandle, долго millisecondsTimeout, BOOL hasThreadAffinity, BOOL exitContext) + 0x21 байт
mscorlib.dll! System.Threading.WaitHandle.WaitOne (длинный тайм-аут, BOOL exitContext) + 0x21 байт
mscorlib.dll! System.Threading.WaitHandle.WaitOne (интермедиат миллисекундыTimeout, bool exitContext) + 0x1f байты
mscorlib.dll! System.Threading.WaitHandle.WaitOne() + 0x10 байт
System.Windows.dll! MS.Internal.InternalNetworkStream.EndRead (System.IAsyncResult AsyncResult) + 0x40 байт
System.Windows.dll! MS.Internal.InternalNetworkStream.Read (байт [] буфера, внутр смещение , внутр счет) + 0x38 байт
mscorlib.dll! System.IO.Stream.ReadByte() + 0x28 байт
mscorlib.dll! System.IO.BinaryReader.ReadByte() + 0x1D байт
GenIIIWebClient! GenIIIWebClient.CVRESTLib .HttpMultipartStreamer.ReadHeaders (System.IO.BinaryReader reader) Строка 201 + 0x19 байт
GenIIIWebClient! GenIIIWebClient.CVRESTLib.HttpMultipartStreamer.OnGetResponse (System.IAsyncResult res) Линия 126 + 0xf байт
System.Windows.dll! System.Net.Browser.ClientHttpWebRequest.InvokeGetResponseCallback.AnonymousMethod__18 (объект State2) + 0x11 байт
mscorlib.dll! System.Threading.QueueUserWorkItemCallback.WaitCallback_Context (состояний объекта) + 0x3e байт
mscorlib. длл! System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext ExecutionContext, System.Threading.ContextCallback обратного вызова, состояние объекта, BOOL preserveSyncCtx) + 0x97 байт
mscorlib.dll! System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem .ExecuteWorkItem() + 0x5a байты
mscorlib.dll! System.Threading.ThreadPoolWorkQueue.Dispatch() + 0x1b3 байты
mscorlib.dll! System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() + 0x5 байты
[Род Managed Перехода]
[AppDomain Transition]
[Род Managed Перехода]
Unflagged 5096 5 Worker Worker Thread Thread [во сне, ждать, или присоединиться к] Нормальным [во сне, ждать, или присоединиться к]
mscorlib.dll! System.Threading.WaitHandle.InternalWaitOne (System.Runtime.InteropServices.SafeHandle waitableSafeHandle, длинные millisecondsTimeout, BOOL hasThreadAffinity, BOOL exitContext) + 0x21 байт
mscorlib. dll! System.Threading.WaitHandle.WaitOne (long timeout, bool exitConte х) + 0x21 байт
mscorlib.dll! System.Threading.WaitHandle.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 executeContext, System.Threading.ContextCallback callback, состояние объекта, bool preserveSyncCtx) + 0x97 байт
mscorlib.dll! .Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() + 0x5a байт
mscorlib.dll! System.Threading.ThreadPoolWorkQueue.Dispatch() + 0x1b3 байт
mscorlib.dll! System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() + 0x5 байты
[Род Managed перехода]
[AppDomain Transition]
[Род Managed перехода]
Я только что дал инициализацию списка выстрелом, он, похоже, ничего не улучшил. Я отредактировал исходный вопрос, добавив столы вызовов из 2 потоков. Они оба застревают в вызовах WaitOne(), но я не знаю, с кем ожидает InternalNetworkStream? – steji113
Я не ожидал большого влияния на список Init. Просто предложил. Я не вижу вашего редактирования (потому что у меня нет компьютера сейчас, я пользуюсь телефоном). Я могу предвидеть, что WaitOne вызвал операцию сна. Не используйте WaitOne или Sleep, попробуйте мое первое предложение.Sleeping 1ms не является истинным способом для других потоков. Вы должны использовать сброс и установить. Особенно, если вы зацикливаетесь через некоторое время. –