Из комментариев:
Тогда как же избежать этого? Просто добавьте ключевое слово ожидания?
Нет, вы не можете всего сделать это. (И поэтому ранее предложенный дублированный вопрос на самом деле не был дубликат и hellip, ваш сценарий тонко отличается.) Вам нужно будет отложить удаление до завершения загрузки, но это осложняется вашей необходимостью выполнить еще два программных оператора (по крайней мере, & hellip, невозможно точно знать без a good, minimal, complete code example).
Я делать думаю, вы должны переключиться на awaitable WebClient.DownloadFileTaskAsync()
метода, так как это будет по крайней мере упростить реализацию, что делает его просто сохранить using
заявление.
Вы можете обратиться в другой часть проблемы, захватив возвращенный Task
объект и не не ожидая, пока после ваших других операторов программы выполнили:
using (WebClient wc = new WebClient()) {
Task task = wc.DownloadFileTaskAsync(urlUri, outputFile);
SomeMethod1();
SomeMethod2();
await task;
}
Таким образом, загрузка может быть запущена , ваши другие два метода вызваны, а тогда код будет ждать завершения загрузки. Только после того, как он будет завершен, будет выведен блок using
, позволяющий удалять объект WebClient
.
Конечно, в вашей текущей реализации вы, несомненно, занимаетесь соответствующим событием DownloadXXXCompleted
. Если вы хотите, вы можете продолжать использовать объект таким образом. Но IMHO, как только вы перешли на использование await
, гораздо лучше просто поставить после await
код, который необходимо выполнить при завершении операции. Это сохраняет весь код, относящийся к операции, в одном месте и упрощает реализацию.
Если по каким-то причинам вы не можете использовать await
, то вам придется использовать некий альтернативный механизм для задержки Избавьтесь от WebClient
.Некоторые подходы позволят вам продолжать использовать using
, другие потребуют, чтобы вы вызывали Dispose()
в обработчик события DownloadXXXCompleted
. Без более полного примера кода и четкого объяснения причин, почему await
не подходит, было бы невозможно точно сказать, какой будет лучшая альтернатива.
EDIT:
Поскольку вы подтвердили, что у вас нет доступа к await
в текущем коде, вот несколько других вариантов, совместимых со старым кодом и hellip;
Одна возможность состоит в том, чтобы просто ждать в том же потоке после начала операции:
using (WebClient wc = new WebClient()) {
object waitObject = new object();
lock (waitObject)
{
wc.DownloadFileCompleted += (sender, e) =>
{
lock (waitObject) Monitor.Pulse(waitObject);
};
wc.DownloadFileAsync(urlUri, outputFile);
SomeMethod1();
SomeMethod2();
Monitor.Wait(waitObject);
}
}
(Примечание: можно использовать любую подходящую синхронизацию выше, например, ManualResetEvent
, CountdownEvent
, или даже Semaphore
и/или «тонкие» эквиваленты.Я использую Monitor
просто из-за его простоты и эффективности и воспринимаю как предоставленные читатели могут приспособиться к их предпочтительным средствам синхронизации. Одна очевидная причина, которую можно было бы предпочесть другой, чем Monitor
, заключается в том, что другие типы синхронизации Techni ques не будет подвергать риску наличие самого блока обработчика событий DownloadFileCompleted
, ожидающего завершения методов SomeMethod1()
и SomeMethod2()
. Независимо от того, важно ли это, зависит от того, как долго будут проходить эти вызовы по методу по сравнению с загрузкой файла.)
Вышеупомянутое, однако, блокирует текущий поток. В некоторых случаях это может быть хорошо, но чаще всего операция запускается в потоке пользовательского интерфейса, и этот поток не должен блокироваться на время операции. В этом случае, вы хотите отказаться от using
вообще и просто вызвать Dispose()
из обработчика события завершения:
WebClient wc = new WebClient();
wc.DownloadFileCompleted += (sender, e) =>
{
wc.Dispose();
};
wc.DownloadFileAsync(urlUri, outputFile);
SomeMethod1();
SomeMethod2();
Это не сработает. Используйте 'await' с' * TaskAsync' – SLaks
@JasonEvans, почему вы говорите «да»? поскольку OP не использует 'await', тогда возникает проблема. –
Большое спасибо за ответы, я сделал это глупые ошибки несколько раз. Тогда как мне избежать этого? Просто добавьте ключевое слово ожидания? – Jenix