Silverlight HttpWebRequest BinaryReader секунда Операция чтения всегда занимает много времени (12 секунд)

1

Я создаю приложение Silverlight, которое использует реализацию H.264 MediaStreamSource для потокового видео в реальном времени с сервера. У меня есть стример Multipart, который я написал, который читает образцы по кадре.

Когда я подключаюсь к серверу, работающему на моем локальном компьютере, для чтения второго байта из потока ответов в функции 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();
    }

Изменение: Вот стек вызовов из двух потоков.

Worker Thread Worker Thread GenIIIWebClient.CVRESTLib.HttpMultipartStreamer.ReadHeaders Обычный [во время сна, ожидания или присоединения]
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 байт
mscorlib.dll! System.Threading.WaitHandle.WaitOne(int millisecondsTimeout, 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(byte [] buffer, int offset, int count) + 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 (object state2) + 0x11 байт
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! System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() + 0x5a байт
mscorlib.dll! System.Threading.ThreadPoolWorkQueue.Dispatch() + 0x1b3 байт
mscorlib.dll! System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() + 0x5 байт
Переход от управляемого к управляемому
[Переход в Appdomain]
Переход от управляемого к управляемому

Unflagged 5096 5 Worker Thread Worker Thread [В режиме ожидания, ожидания или соединения] Обычный [В режиме ожидания, ожидания или соединения]
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 байт
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! System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() + 0x5a байт
mscorlib.dll! System.Threading.ThreadPoolWorkQueue.Dispatch() + 0x1b3 байт
mscorlib.dll! System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() + 0x5 байт
Переход от управляемого к управляемому
[Переход в Appdomain]
Переход от управляемого к управляемому

Теги:
silverlight
httpwebrequest
binaryreader
mediastreamsource

1 ответ

1

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

Вы пробовали использовать waitHandle вместо сна (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
 }
}

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

Список <byte> buffer = new List <byte>();

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

List<byte> buffer = new List<byte>(1024...etc);
  • 0
    Я только что сделал инициализацию списка, похоже, это не сильно улучшило ситуацию. Я отредактировал свой оригинальный вопрос, добавив стеки вызовов из двух потоков. Они оба застряли в вызовах WaitOne (), но я не знаю, кого ожидает InternalNetworkStream?
  • 0
    Я не ожидал большого влияния на список Init. Просто предложили. Я не вижу ваших правок (потому что у меня сейчас нет компьютера, я пользуюсь телефоном). Я могу предвидеть, что WaitOne вызывается из спящего режима. Не используйте WaitOne или Sleep, попробуйте мое первое предложение. Спящий режим 1 мс не подходит для других потоков. Вы должны использовать сброс и установить. Особенно, если вы зацикливаетесь на времени.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню