lambda 表达式中的只读引用变量

Read only reference variable in a lambda expression

这是我的第一个问题。如果我在询问或格式化方面做错了什么,请告诉我!

我的程序必须在 Windows Media Player 控件中播放某些内容,等到它播放完毕,然后继续播放另一个项目。

下面是整个函数:

    public void Play(AxWindowsMediaPlayer player, ref bool audioFileFinished)
    {
        int numberOfIntro = rnd.Next(songIntros.Count); //Randomly select an intro from the list
        string introFilePath = songIntros.ElementAt(numberOfIntro).fullPath;
        player.URL = introFilePath;

        //This task is necessary because the while (!audioFileFinished) will otherwise run in the UI and hang the app.
        Task f = Task.Factory.StartNew(() =>
        {
            while (!audioFileFinished)
            {
            }

            player.URL = fullPath;
        });
    }

当然,Visual Studio 抱怨我可能没有在 lambda 表达式中使用引用变量。这是合乎逻辑的,因为在异步任务中修改引用变量是不好的,我们就这样吧。

但是,我不需要修改它,因为它在程序的其他地方被修改了。这就是为什么它是一个参考变量。

有没有办法以 Visual Studio 接受的方式读取此变量?也许让它成为一个只读变量?如果可以,怎么做?

提前致谢, 利亚姆

这是一种方法,您可能想要更改公认的糟糕名称:

public class Completion : ICompletionNotification
{
    public bool IsCompleted { get; private set; }

    public void Complete() => IsCompleted = true;
}

public interface ICompletionNotification
{
    bool IsCompleted { get; }
}

调用代码会创建一个新的 Completion,但是您的 Play 方法需要一个类型为 ICompletionNotification

的参数
public void Play(AxWindowsMediaPlayer player, ICompletionNotification completion)

...并检查其 IsCompleted 属性.

这样调用者可以创建一个 Completion 并将其传递给 Play() 方法,该方法将其转换为 ICompletionNotification.

var completion = new Completion();
Play(player, completion);

调用方可以调用Complete()表示完成,但接收方不能设置属性。它只能读取它。


CancellationTokenCancellationTokenSource 的工作方式几乎相同。正如文档所说,

A CancellationToken enables cooperative cancellation between threads, thread pool work items, or Task objects.

using CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;

// pass the token to some method, and then when it's done call
source.Cancel();

同理。创建者可以取消它,但是它传递的令牌只能用于查看操作是否被取消。

我最初并没有推荐它,因为从技术上讲你并没有“取消”任何东西。但它是相同的概念,不需要定义新类型。看到它的人会明白你在做什么,或者可以查阅现有文档。

我找到了我的具体案例的答案。我将变量 audioFileFinished 设为静态变量。在任务中执行的方法现在位于与 audioFileFinished 相同的 class 中。我的函数现在看起来像这样:

    public void Play(AxWindowsMediaPlayer player)
    {
        int numberOfIntro = rnd.Next(songIntros.Count); //Randomly select an intro from the list
        string introFilePath = songIntros.ElementAt(numberOfIntro).fullPath;
        player.URL = introFilePath;

        //This task is necessary because the while (!audioFileFinished) will otherwise run in the UI and hang the app.
        Task f = Task.Factory.StartNew(() => Radio.PlayAfterThis(fullPath));
    }

主要 class 中的方法如下所示:

    public static void PlayAfterThis(string path)
    {
        while (!audioFileFinished)
        {

        }
        localPlayer.URL = path;
    }

变量现在被初始化为public static bool audioFileFinished;

感谢@Etienne de Martel 的建议:

Maybe your lambda could even be a method of a class with that field in it.