1

Я создаю приложение 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 перехода]

ответ

1

это трудно увидеть истинную причину здесь, но это может быть что-то связанно с резьбой управления. Первым подозреваемым я вижу здесь m_Running. Сфокусируйтесь на этом. Возможно, некоторые типы поточных материалов различаются для типов проектов.

Вы пытались использовать в WaitHandle вместо того, чтобы дать Sleep (1),

ManualResetEvent waitHandle = new ManualResetEvent(false); 

while(true) 
{ 
    waitHandle.Wait(); 
    waitHandle.Reset(); 

    while(ThereIsAJobToExecute) 
{ 
    // Process the jobs 
    // You should waitHandle.Set() in a callback or when you read it 
} 
} 

Моего второе предложение для линии ниже дает начальному размеру списка

Список < байты> buffer = new Список < byte>();

Начальный размер для списка <> типа не означает, что предел такого размера массива. Если вы не дадите предопределенный размер, List изменяет размеры. Поэтому предоставление ожидаемого числа является плюсом.

List<byte> buffer = new List<byte>(1024...etc); 
+0

Я только что дал инициализацию списка выстрелом, он, похоже, ничего не улучшил. Я отредактировал исходный вопрос, добавив столы вызовов из 2 потоков. Они оба застревают в вызовах WaitOne(), но я не знаю, с кем ожидает InternalNetworkStream? – steji113

+0

Я не ожидал большого влияния на список Init. Просто предложил. Я не вижу вашего редактирования (потому что у меня нет компьютера сейчас, я пользуюсь телефоном). Я могу предвидеть, что WaitOne вызвал операцию сна. Не используйте WaitOne или Sleep, попробуйте мое первое предложение.Sleeping 1ms не является истинным способом для других потоков. Вы должны использовать сброс и установить. Особенно, если вы зацикливаетесь через некоторое время. –