我有以下C#代码。

var databaseRestore = new Microsoft.SqlServer.Management.Smo.Restore();
//databaseRestore.PercentComplete += CompletionStatusInPercent;
//databaseRestore.PercentCompleteNotification = 10;
//databaseRestore.Complete += Restore_Completed;

...

var complete = Observable
    .FromEventPattern(databaseRestore, "Complete")
    .Select(x=>x.EventArgs as ServerMessageEventArgs)
    .Select(x=>x.Error.Message)
    .Take(1)
    .DumpLive("Complete");

var percentComplete = Observable
    .FromEventPattern(databaseRestore, "PercentComplete")
    .Select(x=>x.EventArgs as PercentCompleteEventArgs)
    .Select(x=>x.Percent)
    .TakeUntil(complete)
    .DumpLive("PercentComplete");

...

databaseRestore.SqlRestore(server);


如果运行此命令,则首先总是来自处理程序的输出(如果我取消注释)。

然后,Linqpad首先显示“ Live Observables”结果标签,其中包含


可观察到的“完成”,已经完成,并带有最终结果消息。
“ PercentComplete”,仍在等待,并带有“-”(还没有条目?)


我想要的只是摆脱使用反应式扩展的事件。
首先应该观察到“ PercentComplete”,并根据实际进度进行更新。
然后“完成”最后一条消息。

问题:如何正确设置可观察物?

最佳答案

我的猜测是这是DumpLive()如何在主线程上使用Dispatcher的错误。

您是在主线程上运行数据库还原,还是在阻止主线程等待完成信号?

我做了一些实验,并使用DumpLive()在后台线程上运行了Observable-如果主线程被阻塞(例如,使用Wait或Thread.Sleep),则UI不会更新。

即使在不同的线程上,DumpLive()似乎也只能更新主线程上的UI。我猜想它需要在与主线程关联的Dispatcher上呈现更新。

使用DumpLive时,LINQPad在可观察对象完成之前不会终止执行,因此,如果您在主线程上有任何阻塞代码,请将其删除,然后查看它是否有效。

这是我的实验代码。在下面的示例中添加任一DumpLive()子句后,您将立即看到阻塞行为:

void Main()
{
    Task.Run(() => {
    var progressor = new Progressor();
    var complete = Observable
        .FromEventPattern(
        h => progressor.Complete += h,
        h => progressor.Complete -= h)
        .Select(_ => "Complete")
        .Take(1);
        // append this to see blocking
        //.DumpLive();

        complete.Subscribe(Console.WriteLine);


    var percentComplete = Observable
        .FromEventPattern<PercentCompleteEventArgs>(
        h => progressor.PercentComplete += h,
        h => progressor.PercentComplete -= h)
        .TakeUntil(complete)
        .Select(i => "PercentComplete " + i.EventArgs.PercentComplete);
        // append this to see blocking
        // .DumpLive();

        percentComplete.Subscribe(Console.WriteLine);
    });

    Thread.Sleep(5000);
}

public class Progressor
{
    public Progressor()
    {
        Observable.Interval(TimeSpan.FromSeconds(1)).Take(10)
            .Subscribe(
            i => RaisePercentComplete(((int)i+1) * 10),
            () => RaiseComplete());
    }

    private void RaiseComplete()
    {
        var temp = Complete;
        if(temp != null)
        {
            temp(this, EventArgs.Empty);
        }
    }

    private void RaisePercentComplete(int percent)
    {
        var temp = PercentComplete;
        if(temp != null)
        {
            temp(this, new PercentCompleteEventArgs(percent));
        }
    }

    public event EventHandler Complete;
    public event EventHandler<PercentCompleteEventArgs> PercentComplete;
}

public class PercentCompleteEventArgs : EventArgs
{
    public int PercentComplete { get; private set; }

    public PercentCompleteEventArgs(int percent)
    {
        PercentComplete = percent;
    }
}

关于c# - 在具有相对扩展的linqpad中还原数据库时显示进度,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20424433/

10-09 03:52