2009-08-24 3 views
3

그림을 다운로드하고 나중에 그림 상자에 표시하고 싶습니다.폼이 얼어 붙는 것을 방지하십시오.

는 처음 나는 다음과 같이했다 :

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 메서드에 의해.

문제를 해결하는 데 가장 좋은 시간은 언제입니까?

답변

13

기본적으로 UI 스레드가 다운로드를 완료하고 있었기 때문에 원래 그 일이 발생했기 때문에 작업이 취소되었거나 새로 고침 (동기화)되지 않았습니다. 이제는 UI 스레드가 계속 스레드를 시작한 다음 다운로드가 완료되지 않은 로컬 파일을 그림 상자에 할당하려고합니다. 다음 중 하나를 시도하십시오.

다운로드 작업을 완료하려면 background worker을 사용해야합니다.

매우 편리한 이벤트가 있습니다. 다운로드 할 수있는 DoWork.

작업이 완료되면 실행되는 RunWorkerCompleted 이벤트가 있습니다. 이미지를 설정할 위치 (pictureBox2.Picture = localFile;).

확실히 확인해 볼 가치가 있습니다. 달성하고자하는 것을 완료하는 데 가장 적합한 방법이라고 생각합니다.

또는

당신이 스레드를 사용하여 고수 할 경우. 당신은 당신이 Thread.Start()를 완료 한 후 이미지 할당을 꺼내하고 작업자 스레드 기능이를 넣어 수 :

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; 
    } 
} 
+1

BackgroundWorker에 당신이 검색하는 것은 분명하다. 방금 사용 했으므로 사용하기가 쉽습니다. DoWork 이벤트에 무언가를 추가하고 결과를 e.Result에 넣은 다음이 값을 RunWorkerCompleted 이벤트에 사용하십시오. 또는 장기 실행 기능이 더 복잡한 경우에는 ((MethodInvoker) e.Argument) .Invoke(); 장기 실행 기능 내에서 BeginInvoke를 사용하여 GUI 요소를 업데이트하십시오. GUI 스레드에서 무언가가 진행되고 있는지 판별하려면 backgroundWorker.IsBusy; – Oliver

+0

자세한 내용은 다음을 참조하십시오. http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx – Oliver

+0

@Oliver : 사실, 그들은 꽤 개발자 친화적이며, 우리를위한 우리의 일. – ThePower

2

가장 간단한 해결책은 바로 Picturebox.LoadAsync() 방법을 사용하고로드에 대한 PictureBox를 걱정하게하는 것 그것 백그라운드에서. 오류를 확인해야하는 경우 PictureBox의 LoadCompleted 이벤트를 사용하십시오.

라인과 같은 :

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

당신이 필요합니다.

1)이 일어나고있는 것을 표시하기 위해 UI를 업데이트 : 사용자가 당신이해야 할 일을하는 과정을 시작

1

. IE : 모든 필드를 비활성화하고 "파일을 다운로드 중입니다. 기다려주십시오 ..."라는 메시지를 표시하십시오. 우선적으로 일종의 진행 표시기 (죄송합니다. WebClient가 진행 상황 등을 지원하는지 잘 모르겠지만 다운로드가 완료되면 UI를 업데이트해야합니다.)

2) WebClient의 'DownloadFileCompleted'에 이벤트 처리기를 연결합니다.

3) WebClient의 DownloadFileAsync 메서드를 사용하여 다른 스레드에서 다운로드를 시작합니다. 스레드를 스스로 돌릴 필요가 없습니다.

4) 'DownloadFileCompleted'이벤트가 발생하면 양식의 호출 메소드를 사용하여 UI 스레드로 다시 전화를 겁니다. 이건 매우 중요합니다.

참조 : http://weblogs.asp.net/justin_rogers/pages/126345.aspx

과 : 필드 등)를 활성화 다시 : 이벤트가 파일을 열고 필요에 따라 (IE를 UI를 업데이트 UI 스레드에 다시 전달되면 http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx

5).

가죽.

+0

예, WebClient에는 DownloadProgressChanged 및 DownloadCompleted 이벤트가 있습니다. –

1

은 스레딩 문제와 관련,하지만 당신은 당신이 할 수있는 디스크에 사진을 저장하기위한 다른 요구 사항이없는 경우하지 :

WebClient client = new WebClient(); 
byte[] data = client.DownloadData(item.Url); 
MemoryStream ms = new MemoryStream(data); 
Bitmap img = new Bitmap(ms); 
pictureBox.Image = img; 
+0

이점은 무엇입니까? – Kai

+0

불필요한 파일로 디스크를 어지럽히 지 않습니다. 특히 파일이 큰 경우. –

+0

동일한 사진을 계속해서 다운로드하지 않고 디스크에 저장하고 다시 다운로드하기 전에 파일이 존재하는지 확인하는 것이 더 효율적일 때만 유용합니다. –

관련 문제