Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
175 views
in Technique[技术] by (71.8m points)

c# - Can I stop WPF from executing UI actions out of the order in my code

I have a problem where it takes a few seconds to generate a report and send it to the printer (creating the RDLC report container is slow).

To make sure the user is aware of what is going on I attempted to update a status line before and after doing the print//.

Status = "Printing Report.";
OnPropertyChanged("Status");
//Create a hidden window to host the report control
ReportWindow rw = new ReportWindow();
rw.PrintReport();
rw.Close();  
Status = "Printing Report complete.";
OnPropertyChanged("Status");

What I wanted to happen was:

  1. Status is updated indicating that the report is being created and will be printed as soon as its done.
  2. The report is created and printed over several seconds.
  3. Status is updated to show success.

What actually happens is:

  1. Nothing is shown on the UI
  2. After a few seconds, the report is created and printed
  3. Status is updated indicating that the report is being created and will be printed as soon as its done.
  4. Immediately afterwards status is updated to show success. This happens fast enough that the first message is at most strobed on the screen for a single screen refresh; at worst it's never seen at all unless I interrupt with a break point.

I've had similar issues before with WPF prioritizing doing something slow on the UI thread above updating the UI to indicate that it's going to be busy for a few seconds; but in this case I'm not able to remove the heavy item from the UI thread (or do something else) to avoid the issue.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

... but in this case I'm not able to remove the heavy item from the UI thread (or do something else) to avoid the issue

In this case you could create a new window that launches in a separate thread and display this one while the report is printing:

Wait screen during rendering UIElement in WPF

Once the report has been printed you just close the new window:

Window tempWindow = null;
Thread newWindowThread = new Thread(new ThreadStart(() =>
{
    SynchronizationContext.SetSynchronizationContext(
    new DispatcherSynchronizationContext(
        Dispatcher.CurrentDispatcher));

    tempWindow = new Window();
    tempWindow.Content = new ProgressBar() { IsIndeterminate = true };
    tempWindow.Closed += (ss, ee) =>
    Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);

    tempWindow.Show();
    System.Windows.Threading.Dispatcher.Run();
}));

newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.IsBackground = true;
newWindowThread.Start();

ReportWindow rw = new ReportWindow();
rw.PrintReport();
rw.Close();

if (tempWindow != null)
    tempWindow.Dispatcher.Invoke(new Action(() => tempWindow.Close())); 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...