Код потока срабатывает один раз, а потом его полномочия всё

Опять какая-то странная ситуация. Не могу понять, в чём проблема.
Есть массив UserControlов, в каждом из которых есть экземпляр класса TwitchStreamInfo и кнопка. При нажатии на кнопку, в классе главной формы выполняется обработчик, который создаёт поток. В поток надо передать экземпляр TwitchStreamInfo, чтобы потом использовать его в обработчике события завершения потока.

        public static int GetStreamPlaylistUrl(TwitchStreamInfo aStream, out string playlistUrl)
        {
            playlistUrl = string.Empty;
            int res = 404;
            if (!string.IsNullOrEmpty(aStream.imageAnimatedPreviewUrl))
            {
                int n = aStream.imageAnimatedPreviewUrl.IndexOf(".net/");
                if (n > 0)
                {
                    string server = aStream.imageAnimatedPreviewUrl.Substring(0, n + 4);
                    playlistUrl = $"{server}/{aStream.streamId}/chunked/index-dvr.m3u8";
                    res = FileDownloader.GetContentLength(playlistUrl, out _);
                }
            }
            return res;
        }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using static TwitchPrimeDownloader.Utils;

namespace TwitchPrimeDownloader
{
    public class ThreadGetVodPlaylist
    {
        public string playlistUrl;
        public string playlistString;
        public int errorCode;
        public TwitchStreamInfo _streamInfo;
        public List<string> resPlaylist;
        public List<object> controls = new List<object>();
        public event Action<object, int> Completed;

        public void Work(object aContext)
        {
            errorCode = GetStreamPlaylistUrl(_streamInfo, out playlistUrl);
            if (errorCode == 200)
            {
                errorCode = DownloadString(playlistUrl, out playlistString);
                if (errorCode == 200)
                {
                    resPlaylist = playlistString.Split(new string[] { "\n" },
                        StringSplitOptions.RemoveEmptyEntries).Where(s => s.EndsWith(".ts")).ToList();

                }
            }
            (aContext as SynchronizationContext).Send(OnComplete_Context, this);
        }
        
        private void OnComplete_Context(object obj)
        {
            Completed?.Invoke(obj, errorCode);
        }
    }
}
        private void ThreadGetVodPlaylist_Complete(object sender, int errorCode)
        {
            if (errorCode == 200)
            {
                ThreadGetVodPlaylist thrObj = sender as ThreadGetVodPlaylist;
                FrameDownload frd = new FrameDownload(null);
                frd.Parent = panelDownloads;
                frd.Location = new Point(0, 0);

                framesDownload.Add(frd);

                tabPageDownload.Text = "Скачивание (" + framesDownload.Count.ToString() + ")";
                StackFramesDownload();

                foreach (object ctl in thrObj.controls)
                {
                    if (ctl is ToolStripMenuItem)
                        (ctl as ToolStripMenuItem).Enabled = true;
                    else
                        (ctl as Control).Enabled = true;
                }
            }
            else
                MessageBox.Show($"Error {errorCode}");
        }


        private void Event_DownloadButtonClick(object sender)
        {
            FrameStream frameStream = sender as FrameStream;
            frameStream.btnDownload.Enabled = false;
            ThreadGetVodPlaylist threadGetVodPlaylist = new ThreadGetVodPlaylist();
            threadGetVodPlaylist._streamInfo = frameStream.streamInfo;
            threadGetVodPlaylist.controls.Add(frameStream.btnDownload);
            threadGetVodPlaylist.Completed += ThreadGetVodPlaylist_Complete;

            Thread thr = new Thread(threadGetVodPlaylist.Work);
            thr.Start(fContext);
        }
    }

Это срабатывает один-два раза, а потом начинает задумываться на проверке urlа и выдаёт ошибку 403.
ничё не пойму, почему так :thinking:
Раньше работало нормально, а после допиливания стало так. Старая версия кода не сохранилась.
вспомнилась картинка

Это где?

Один-два раза после чего? После перезапуска программы снова работает?

Гит надо использовать и всегда будет любая старая версия, и легко можно посмотреть что поменялось.

Ошибка 403 говорит о том, что доступ к запрашиваемой странице запрещён или у пользователя нет прав на просмотр контента.

после запуска

да

Это я так думал, но дело не в этом. Сейчас в дебаггере докопался, что он спотыкается на строчке string t = webClient.DownloadString(url). Оно далеко не каждый раз срабатывает, почему-то :thinking:

А вебклиент новый на каждый запрос? Куки не хранятся?

почему тогда после перезапуска права снова появляются? Это webClient гонит.

новый

Там куки не нужны. На Delphi запросы регулярно идут уже почти 3 года и всё работает. Твич по IP не банит.
Это просто какая-то хрень с DownloadString.

Возможно поможет дока:

Ну так я и говорю, что если хранятся, то может быть из-за этого. Больше по идее ничего не должно отличать запросы сразу после запуска и позже, если веб-клиент новый на каждый запрос и больше никакого состояния в том коде нет.

В другой программе (тоже твич, тоже C#) запросы идут вообще по таймеру очень много раз в сутки. Но там ни разу не было такого затыка.

Можно например через Fiddler посмотреть нет ли чего-то странного в запросах с ошибкой, есть ли отличие от успешных. (у веб-клиента вроде надо указать прокси на 127.0.0.1 и порт фиддлера)

если делать это по кнопке

        private void button1_Click(object sender, EventArgs e)
        {
            string url = "https://d2nvs31859zcd8.cloudfront.net/2aac36b5ae75bc7e0257_miramisu_42307029086_1618331665/chunked/index-dvr.m3u8";
            WebClient wc = new WebClient();
            string t = wc.DownloadString(url);
            wc.Dispose();
            memoDebug.Text = t;
            tabControlMain.SelectedTab = tabPageDebug;
        }

то работает.
А в потоке виснет на DownloadString() :thinking:

Нашел косяк! Я просто забывал освобождать ответ от сервера после проверки ссылки. По-этому, DownloadString() зависал.
Наверное, это как-то связано с ограничением на максимальное количество одновременных подключений.
Однако, я не понял, почему оно тогда в других проектах работает? :thinking: