Backgroundworker停止两次

时间:2013-09-15 16:03:28

标签: c# wpf backgroundworker

我遇到了后台工作者的问题。 我不知道如何描述它。 实际上它是一个游戏和背景工作者x x milisecs我更新进度条,检查是否有人丢失/赢了或时间到了。 如果有人赢了比赛就结束了。 如果两名球员都输了/时间到了,那么比赛将进入下一轮。 当两名球员输球时都会出现问题。 SetTime方法中的方法NextRound, 跑了两次。 这是代码:

void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    this.SetTime(e.ProgressPercentage);
}

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    Thread.Sleep(3000);
    BackgroundWorker worker = sender as BackgroundWorker;
    int tick = ProgLib.maxTime * 10;

    for (int i = 1; i <= 100; i++)
    {
        if ((worker.CancellationPending == true))
        {
            e.Cancel = true;
            break;
        }
        else
        {
            // Perform a time consuming operation and report progress.
            Thread.Sleep(tick);
            worker.ReportProgress(i);
        }
    }
}

private void SetTime(double k)
{
    this.time.Bar1.Value = k;
    this.time.Bar2.Value = k;

    if (k >= 100 || (Gallery1.hasLost() && Gallery2.hasLost()) || ((Gallery1.isWinner() || Gallery2.isWinner())))
    {
        if (bw == null)
            return;
        bw.CancelAsync();
        bw.Dispose();
        bw = null;

        saveData();
        ProgLib.isAnyoneWinner(Gallery1.isWinner(), Gallery2.isWinner());
        if (ProgLib.gameHasended())
        {
            gameHasEnded();

        }
        else
        {
            next_round();
        }
    }
}

private void next_round()
{
    Thread nextRoundThread = new Thread((Object Send) =>
    {
        MainThread.Send((Object send) =>
        {
            Gallery1.hidePanel.Visibility = Visibility.Visible;
            Gallery2.hidePanel.Visibility = Visibility.Visible;

            ProgLib.nextLetter();//goes to next letter
            LetterToPlay1.setLetter(ProgLib.getArrabicLetter(ProgLib.getCurentLetter()));//sets the next letter
            LetterToPlay2.setLetter(ProgLib.getArrabicLetter(ProgLib.getCurentLetter()));

        }, null);

        Thread SoundThread = new Thread((Object send) =>
        {
            //Here Must Delay enought so the animation stops the hear the bell and the the letter, and then the game starts
            Thread.Sleep(1800);
            ProgLib.playOtherSound(ProgLib.Sounds.Chimes);//Bell Sound
            Thread.Sleep(100);
            //ProgLib.PlayLetterSound(ProgLib.getCurentLetter());//Letter Sound
            ProgLib.playOtherSound(ProgLib.Sounds.Cat_Yawn);//TestOnly
        });
        SoundThread.IsBackground = true;
        SoundThread.Start();

        Thread.Sleep(3000);
        MainThread.Send((Object send) =>
        {
            Gallery1.refresh();//galleries refresh so that the magician hides.
            Gallery2.refresh();//
            Gallery1.hidePanel.Visibility = Visibility.Hidden;//hide the Big Magician of  mistakes
            Gallery2.hidePanel.Visibility = Visibility.Hidden;
        }, null);

    });
    nextRoundThread.IsBackground = true;
    nextRoundThread.Start();

    bw = new BackgroundWorker();
    bw.WorkerSupportsCancellation = true;
    bw.WorkerReportsProgress = true;
    bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
    bw.RunWorkerAsync();
}

1 个答案:

答案 0 :(得分:3)

您的代码中存在线程竞争。您的工作人员将调用ReportProgress()并立即迭代循环。通过CancellationPending属性检查并再次入睡。

您的SetTime()方法稍后运行 。并调用CancelAsync(),但由于工作人员正在休眠,因此完全没有任何影响。直到它再次唤醒,再次调用ReportProgress(),迭代循环并然后将CancellationPending设置为true。

即使您已经结束游戏,也会再次调用您的SetTime()方法。

线程充斥着这样的问题。创可贴是在Sleep()调用后检查CancellationPending。其中99.999%的工作时间。达到100%需要使用适当的锁定进行非常激烈的重写。