none
问个WP多线程调度的问题 RRS feed

  • 问题

  • 问个WP多线程的问题

    protected override void OnBackKeyPress(CancelEventArgs e)
            {
                 xBackgroundWorker.CancelAsync();
                 mConcelDownloadSync.WaitOne();
            }

    想在OnBackKeyPress事件中通知一个后台线程退出,然后等待后台线程退出完后再返回到上一页(后台线程最后会执行mConcelDownloadSync.Set()语句)

    但是发现如果OnBackKeyPress方法里面的语句没有执行完并退出OnBackKeyPress方法,系统貌似永远不会去调用其他线程运行,最后我的OnBackKeyPress方法一直等待mConcelDownloadSync.Set()执行,而执行mConcelDownloadSync.Set()语句的子线程又一直等待OnBackKeyPress的退出,貌似造成了死锁

    请问,有没有方法解决,谢谢

    2012年5月6日 4:24

答案

  • 多谢关注,已解决。

    由于自己的方法调用中参数没传对,产生了逻辑错误才出现这情况。在写重现代码时才发现的,真奔溃............

    问题解决了,怎么结贴呢

    2012年5月13日 3:42

全部回复

  • 你可以参考下文解决死锁问题:

    http://developer.51cto.com/art/200908/141606.htm

    2012年5月7日 7:32
  • 文章不错  可惜里面没有答案

    在程序中我觉得好像是当前线程如果没有执行完提出的话,子线程是不会被系统调度执行的。

    所以我虽然在主线程中通知子线程退出然后等待,但是子线程需要主线程执行完毕退出之后才会被操作系统进行调用并执行。不知道我这么猜测是否正确,如果真是这样子的话有没有什么办法使主线程在等待时,子线程也能执行

    2012年5月7日 13:30
  • 你好,

    请给出重现该问题的代码,或直接将重现代码上传到skydrive并贴出链接。

    2012年5月8日 10:03
    版主
  • 这个是在页面构造函数中初始话子线程(用BackgroudWork来作为子线程)

    public DownloadPage()
            {
                InitializeComponent();
                //mConcelDownloadSync = new ManualResetEvent(false);
                xPathList = (App.Current asApp).XiaoRenShuPaths;
                xOfflineHelper = OfflineHelper.Instance;
                xCurrentImage = newBitmapImage();
                xOfflineHelper.ImageSavedEvent += OnImageSaved;
                xOfflineHelper.DownloadXrsPicErrorEvent += OnDownloadedXrsError;
                xDescription = (App.Current asApp).XiaoRenShuDescription;
                imgPreview.Loaded += imgPreview_Loaded;
     
                xBackgroundWorker = newBackgroundWorker();
                xBackgroundWorker.WorkerSupportsCancellation = true;
                xBackgroundWorker.DoWork +=
                    (sender, args) => xOfflineHelper.DownloadXRS(xId, xPathList, xTitle, xDescription, sender asBackgroundWorker);
                xOfflineHelper.DownloadedXrsFinishEvent += OnDownloadedXrsFinish;
            }

    在DownloadXRS方法中会判断子线程是否被通知要退出(以下加粗部分为判断语句)

    AutoResetEvent mPicDownloadSync = new AutoResetEvent(false);
                bool lSaveResult;
                if (!xFileStoreage.DirectoryExists(string.Concat(xXIAO_REN_SHU_DIR, "/", aId)))
                    xFileStoreage.CreateDirectory(string.Concat(xXIAO_REN_SHU_DIR, "/", aId));
                for (int i = 0; i < aPicList.Length; i++)
                {
                    lSaveResult = false;
                    if (aBackgroundWorker.CancellationPending)
                        return false;
                    string lDownloadPath = string.Concat(xDOMAIN, aPicList[i]);
                    string mSavePath = string.Concat(xXIAO_REN_SHU_DIR, "/", aId, "/",
                                                 lDownloadPath.Replace(xDOMAIN, "").Remove(0, 1).Replace("/""-"));
                    if (!xFileStoreage.FileExists(mSavePath))
                    {
                        byte[] mContentArray = new byte[0];
                        PicDownloader.DownloadPic(lDownloadPath, e =>
                                                                     {
                                                                         mContentArray = new byte[e.Length];
                                                                         mContentArray = e;
                                                                         lSaveResult = SaveImageToDisk(aId, mSavePath, mContentArray);
                                                                         mPicDownloadSync.Set();
                                                                     }, () =>
                                                                            {
                                                                                if (DownloadXrsPicErrorEvent != null)
                                                                                    DownloadXrsPicErrorEvent();
                                                                                mPicDownloadSync.Set();
                                                                            });
     
                        mPicDownloadSync.WaitOne();
                    }
                    else
                    {
                        lSaveResult = true;
                        if (ImageSavedEvent != null)
                            ImageSavedEvent(mSavePath);
                    }
                    XElement mPicNode = new XElement("Pictures");
                    mPicNode.SetAttributeValue("Number", i);
                    mPicNode.SetAttributeValue("IsDownload", lSaveResult ? 1 : 0);
     
                    mPicNode.Value = aPicList[i];
                    aImageNode.Add(mPicNode);

    页面加载完成后会直接调用启动BackgroundWorker运行,此时子线程开始运行。

    void Loaded(object sender, RoutedEventArgs e)
            {
                    xBackgroundWorker.RunWorkerAsync();
            }

    直到按下手机上的后退键通知子线程停止时,子线程再停止

    protected override void OnBackKeyPress(NavigationEventArgs e)
            {
                xBackgroundWorker.CancelAsync();
            }

    问题就是,原本的设计之中当按下返回键之后会等待子线程退出(使用AutoResetEvent或者ManualResetEvent进行同步),然后页面再跳转的但是如果在OnBackKeyPress方法中等待的话,系统会一直停在该方法中,而子线程没有被执行。子线程没有被执行,那么子线程就不会退出,所以主线程就一直等待。

    有没有方法解决这个情况?让主线程等待的同时,子线程也能够被执行

    2012年5月8日 12:34
  • 你好,

    为了解决这一问题,请提供一个简化了的、能够重现问题的完整代码。您不需要贴出项目的完整源码,我们只需要能够重现这一问题的最简单的代码。您可以移除项目中任何保密信息或商业逻辑。您可以将项目上传到skydrive并贴出链接。

    2012年5月9日 8:43
    版主
  • 多谢关注,已解决。

    由于自己的方法调用中参数没传对,产生了逻辑错误才出现这情况。在写重现代码时才发现的,真奔溃............

    问题解决了,怎么结贴呢

    2012年5月13日 3:42