C# 编写一个等待bool的异步方法

C# 编写一个等待bool的异步方法,c#,.net,asynchronous,async-await,C#,.net,Asynchronous,Async Await,我想写一个方法,它将等待变量设置为true 这是psudo代码 bool IsSomethingLoading = false SomeData TheData; public async Task<SomeData> GetTheData() { await IsSomethingLoading == true; return TheData; } bool IsSomethingLoading=false 数据中的一些数据; 公共异步任务GetTheData()

我想写一个方法,它将
等待变量设置为true

这是psudo代码

bool IsSomethingLoading = false
SomeData TheData;

public async Task<SomeData> GetTheData()
{
   await IsSomethingLoading == true;
   return TheData;
}
bool IsSomethingLoading=false
数据中的一些数据;
公共异步任务GetTheData()
{
等待IsSomethingLoading==true;
返回数据;
}
数据将由Prism事件与
IsSomethingLoading
变量一起设置

我有一个对
GetTheData
方法的调用,但是我希望它运行async(现在如果数据没有准备好,它只返回null)(这会导致其他问题)


有什么方法可以做到这一点吗?

在许多类似的情况下,您需要的是一个
TaskCompletionSource

您可能有一个方法能够在某个时间点生成数据,但它不使用任务来完成此操作。可能有一个方法接受提供结果的回调,或者触发一个事件以指示有结果,或者只是使用
线程
线程池
编写代码,而您不是inc重新使用
任务。运行

public Task<SomeData> GetTheData()
{
    TaskCompletionSource<SomeData> tcs = new TaskCompletionSource<SomeData>();
    SomeObject worker = new SomeObject();
    worker.WorkCompleted += result => tcs.SetResult(result);
    worker.DoWork();
    return tcs.Task;
}
public任务GetTheData()
{
TaskCompletionSource tcs=新的TaskCompletionSource();
SomeObject worker=新的SomeObject();
worker.WorkCompleted+=result=>tcs.SetResult(result);
工人。道工();
返回tcs.Task;
}
虽然您可能需要/希望向worker或其他类提供
TaskCompletionSource
,或者以其他方式将其公开到更广泛的范围,但我发现它通常不需要,即使在适当的时候它是一个非常强大的选项

您也可以使用
Task.fromsync
创建基于异步操作的任务,然后直接返回该任务,或者
wait
将其包含在代码中。

您可以使用a作为信号,
wait
表示:

TaskCompletionSource<bool> IsSomethingLoading = new TaskCompletionSource<bool>();
SomeData TheData;

public async Task<SomeData> GetTheData()
{
   await IsSomethingLoading.Task;
   return TheData;
}

我提出了一个非常简单的解决方案,但不是回答原始问题的最佳方案,如果您不考虑高速性能:

...
public volatile bool IsSomethingLoading = false;
...
public async Task<SomeData> GetTheData()
{
    // Launch the task asynchronously without waiting the end
    _ = Task.Factory.StartNew(() =>
    {
        // Get the data from elsewhere ...
    });

    // Wait the flag    
    await Task.Factory.StartNew(() =>
    {
        while (IsSomethingLoading)
        {
            Thread.Sleep(100);
        }
    });

   return TheData;
}
测试代码:

<Label x:Name="label1" Content="Label" HorizontalAlignment="Left" Margin="111,93,0,0" VerticalAlignment="Top" Grid.ColumnSpan="2" Height="48" Width="312"/>
public partial class MainWindow : Window
{
    // volatile keyword shall be used to avoid compiler optimizations
    // and potential multithread issues when accessing IsSomethingLoading
    // from other threads.
    private volatile bool IsSomethingLoading = false;

    public MainWindow()
    {
        InitializeComponent();

        _ = TestASyncTask();
    }

    private async Task<bool> TestASyncTask()
    {
        IsSomethingLoading = true;

        label1.Content = "Doing background task";

        // Launch the task asynchronously without waiting the end
        _ = Task.Factory.StartNew(() =>
        {
            Thread.Sleep(2000);
            IsSomethingLoading = false;
            Thread.Sleep(5000);
            HostController.Host.Invoke(new Action(() => label1.Content = "Background task terminated"));
        });
        label1.Content = "Waiting IsSomethingLoading ...";

        // Wait the flag    
        await Task.Run(async () => { while (IsSomethingLoading) { await Task.Delay(100); }});
        label1.Content = "Wait Finished";

        return true;
    }

}

/// <summary>
/// Main UI thread host controller dispatcher
/// </summary>
public static class HostController
{
    /// <summary>
    /// Main Host
    /// </summary>
    private static Dispatcher _host;
    public static Dispatcher Host
    {
        get
        {
            if (_host == null)
            {
                if (Application.Current != null)
                    _host = Application.Current.Dispatcher;
                else
                    _host = Dispatcher.CurrentDispatcher;
            }

            return _host;
        }
    }
}
公共部分类主窗口:窗口
{
//volatile关键字应用于避免编译器优化
//访问IsSomethingLoading时可能出现的多线程问题
//从其他线程。
私有易失性bool IsSomethingLoading=false;
公共主窗口()
{
初始化组件();
_=TestASyncTask();
}
专用异步任务TestASyncTask()
{
IsSomethingLoading=true;
标签1.Content=“正在执行后台任务”;
//异步启动任务而不等待结束
_=Task.Factory.StartNew(()=>
{
《睡眠》(2000年);
IsSomethingLoading=false;
睡眠(5000);
HostController.Host.Invoke(新操作(()=>label1.Content=“后台任务终止”);
});
label1.Content=“等待是一个正在加载的…”;
//等着国旗
wait Task.Run(异步()=>{while(IsSomethingLoading){wait Task.Delay(100);}});
标签1.Content=“等待完成”;
返回true;
}
}
/// 
///主UI线程主机控制器调度程序
/// 
公共静态类主机控制器
{
/// 
///主播
/// 
专用静态调度程序_主机;
公共静态调度程序主机
{
得到
{
如果(_host==null)
{
if(Application.Current!=null)
_主机=Application.Current.Dispatcher;
其他的
_host=Dispatcher.CurrentDispatcher;
}
返回主机;
}
}
}
这项工作对我来说:

while (IsLoading) await Task.Delay(100);
while (IsLoading) await Task.Delay(100);