如何在wp7中使用多线程?

时间:2012-02-02 09:40:27

标签: c# multithreading windows-phone-7

我正在开发一个wp7应用程序。我需要从服务器下载一些文件到我的手机。从列表框中选择文件。当试图下载单个项目时,下载工作完美。但是,当我尝试同时下载多个项目时,会发生错误。如何同时下载多个项目?

这是我的下载文件代码。

IList<Item> selectedItems = documents.Where( p => p.IsChecked == true ).ToList();
foreach ( var item in selectedItems )
{
   FileDownload objDownload = new FileDownload();

   objDownload.FileName = item.Title;
   objDownload.Url = item.Link;
   objDownload.DocId = item.DocId;

   ThreadPool.QueueUserWorkItem( t =>
   {
     Dispatcher.BeginInvoke( () =>
     {
       objDownload.DownloadFile();
     } );
     Thread.Sleep( 0 );
   } );
}

这是FileDownload类

中的DownloadFile()方法
public void DownloadFile()
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create( Url );
    request.AllowReadStreamBuffering = false;
    request.BeginGetResponse( new AsyncCallback( DownloadFileData ), request );
}

private void DownloadFileData( IAsyncResult result )
{
    try
    {
        AddToDownloadList();
        IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
        string fileName = "DownloadedFiles\\" + FileName;
        if ( !isf.DirectoryExists( "DownloadedFiles" ) )
            isf.CreateDirectory( "DownloadedFiles" );

        if ( !isf.FileExists( fileName ) )
        {
            IsolatedStorageFileStream streamToWriteTo = new IsolatedStorageFileStream( fileName, FileMode.Create, isf);
            HttpWebRequest request = (HttpWebRequest)result.AsyncState;
            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse( result );
            Stream str = response.GetResponseStream();
            byte [ ] data = new byte [ 16 * 1024 ];
            int read;
            long totalValue = response.ContentLength;
            while ( ( read = str.Read( data, 0, data.Length ) ) > 0 )
            {
                streamToWriteTo.Write( data, 0, read );
            }
            string file = streamToWriteTo.ToString();
            streamToWriteTo.Close();
        }
        OfflineStatus = true;
    }
    catch ( Exception ex )
    {
        OfflineStatus = false;
    }
}

如何使用多线程下载文件。

3 个答案:

答案 0 :(得分:3)

您的代码存在一些问题:

  • 你必须关闭/处置商店。最好的实践是使用using语句

    使用(var store = IsolatedStorageFile.GetUserStoreForApplication()) {  //任务 }

  • 您无法获得使用多线程下载内容的任何性能* - 连接是瓶颈,而不是每秒CPU周期。

  • 如果你有一个多线程应用程序为同一个位置执行IO,如果(!isf.DirectoryExists(“DownloadedFiles”))将无效。你有竞争条件。如果一个线程开始创建dir并且第二个线程在第一个完成之前检查dir怎么办?

  • 不要使用catch吞下异常(Exception ex)。通常情况下,例外情况都包含有关问题的信息。

我会使用与this one类似的解决方案解决此问题。

*多线程应用程序往往是不确定的,下载可能会更快,但在这种情况下,很可能,它会更慢。

答案 1 :(得分:1)

你正在覆盖你的循环中的objDownload对象,破坏了之前的引用。 创建FileDownload列表并添加每个文件以保持独立。

答案 2 :(得分:1)

关于你的objDownload,

rob是正确的,但你完全没有使用ThreadPool.QueueUserWorkItem + Dispatcher.BeginInvoke,因为WebRequest.BeginGetResponse是异步和非阻塞的。您当前的代码移动到后台线程,然后移动到UI线程,然后执行在后台线程上返回的异步HTTP操作(这非常疯狂)。

旁注:您下载的文件是否较大(例如&gt; 1mb)?如果是这样,您应该使用Background File Transfers - 即使应用程序未运行,它们也会继续下载。