Предотвратить замораживание формы - PullRequest
3 голосов
/ 24 августа 2009

Я хотел бы загрузить изображение и затем показать его в окне для картинок.

сначала я сделал так:

WebClient client = new WebClient();
client.DownloadFile(url, localFile);
pictureBox2.Picture = localFile;

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

Тогда я перешел на это:

public class ParamForDownload
{
    public string Url { get; set; }
    public string LocalFile { get; set; }
}
ParamForDownload param = new ParamForDownload()
        {
            Url = url,
            LocalFile = localFile
        };

      ThreadStart starter = delegate { DownloadMap (param); };
        new Thread(starter).Start();

        pictureBox2.Picture = localFile;



    private static void DownloadMap(ParamForDownload p) 
    {
        WebClient client = new WebClient();
       client.DownloadFile(p.Url, p.LocalFile);
    }

Но теперь я должен сделать что-то вроде «ожидания окончания потока», потому что файл доступен в потоке, и в то же время в файл загружается что-то с помощью метода DownloadMap.

Что лучше всего подождать, чтобы решить эту проблему?

Ответы [ 4 ]

13 голосов
/ 24 августа 2009

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

Вы должны использовать фоновый рабочий для выполнения задачи загрузки.

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

Существует также событие RunWorkerCompleted, которое вызывается после завершения Работы. Где вы можете установить изображение там (pictureBox2.Picture = localFile;).

Это определенно стоит проверить, я думаю, что это самый подходящий способ завершить то, что вы пытаетесь достичь.

Или

Если вы хотите придерживаться темы. Вы можете взять назначение изображения после выполнения Thread.Start() и вставить его в функцию Worker Thread:

private delegate void MyFunctionCaller();

private static void DownloadMap(ParamForDownload p) 
{
    WebClient client = new WebClient();
   client.DownloadFile(p.Url, p.LocalFile);
    DownloadMapComplete(p);
}

private void DownloadMapComplete(ParamForDownload p)
{
if (InvokeRequired == true)
  {
  MyFunctionCaller InvokeCall = delegate { DownloadMapComplete(p); };
  Invoke(InvokeCall);
  }
else
  {
  pictureBox2.Picture = p.LocalFile;
  }
}
2 голосов
/ 24 августа 2009

Самое простое решение - просто использовать метод Picturebox.LoadAsync() и позволить Picturebox беспокоиться о его загрузке в фоновом режиме. Если вам нужно проверить наличие ошибок, используйте событие LoadCompleted (в окне рисунка).

Строка типа:

pictureBox1.LoadAsync(@"http://imgs.xkcd.com/comics/tech_support_cheat_sheet.png");

- это все, что вам нужно.

1 голос
/ 24 августа 2009

Не относится к проблеме потоков, но если у вас нет других требований для сохранения фотографии на диск, вы можете сделать это:

WebClient client = new WebClient();
byte[] data = client.DownloadData(item.Url);
MemoryStream ms = new MemoryStream(data);
Bitmap img = new Bitmap(ms);
pictureBox.Image = img;
1 голос
/ 24 августа 2009

Когда пользователь запускает процесс, вам нужно:

1) Обновите интерфейс, чтобы указать, что что-то происходит. IE: отключить все поля и выложить сообщение «Я загружаю файл, пожалуйста, подождите ...». Преимущественно с каким-то индикатором прогресса (извините, я не уверен, поддерживает ли WebClient прогресс и т. Д., Но вам нужно обновить пользовательский интерфейс, так как загрузка занимает некоторое время).

2) Присоедините обработчик событий к «DownloadFileCompleted» WebClient.

3) Используйте метод DownloadFileAsync WebClient, чтобы начать загрузку в другом потоке. Вам не нужно крутить нити самостоятельно.

4) При возникновении события DownloadFileCompleted перенаправьте вызов обратно в поток пользовательского интерфейса, используя метод invoke формы. ЭТО ОЧЕНЬ ВАЖНО.

См .: http://weblogs.asp.net/justin_rogers/pages/126345.aspx

и: http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx

5) После того, как событие было перенаправлено обратно в поток пользовательского интерфейса, откройте файл и обновите пользовательский интерфейс по мере необходимости (IE: повторно активируйте поля и т. Д.).

кожа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...