報告長時間運行的服務器操作的進度時,出現奇怪的問題。 該應用程序具有客戶端/服務器體系結構,並用C#編寫。客戶使用WPF。在客戶端/服務器環境中報告進度
在客戶端,我創建了進度窗口,並在後臺工作人員開始長時間運行的操作。此操作是通過遠程調用的服務器方法。由於參數服務器方法接受用於報告進度的特殊ProgressContext對象(請參閱下面的代碼)。
一旦服務器開始執行利用CPU /內存有些沉重的操作 - 進度窗口變得凍結。它不響應任何交互並且不更新進度。過了一段時間,繁重的操作完成後 - 進度窗口恢復活力,沒有發生任何事情。
它看起來當我通過後臺工作的實例的服務器和服務器線程就像是重負荷的 - 它的一些如何鎖定窗口BackgroundWorker的是有關。如果我沒有使用遠程調用使用相同的進度窗口 - 問題消失。
報告進度我使用進度窗口,BackgroundWorker的是整個網絡的許多樣品英寸 這裏是進度窗口C#代碼:
public partial class ProgressWindow : Window
{
#region Fields
public static readonly DependencyProperty AutoIncrementProperty =
DependencyProperty.Register(
"AutoIncrement",
typeof(bool),
typeof(ProgressBar),
new UIPropertyMetadata(null));
private readonly BackgroundWorker m_worker;
private CultureInfo m_culture;
private bool m_isCancelled;
private Exception m_error = null;
private Action<IProgressContext> m_workerCallback;
#endregion
#region Constructors
/// <summary>
/// Inits the dialog without displaying it.
/// </summary>
public ProgressWindow()
{
InitializeComponent();
//init background worker
m_worker = new BackgroundWorker();
m_worker.WorkerReportsProgress = true;
m_worker.WorkerSupportsCancellation = true;
m_worker.DoWork += Worker_DoWork;
m_worker.ProgressChanged += Worker_ProgressChanged;
m_worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
AutoIncrement = true;
CancellingEnabled = false;
}
#endregion
#region Public Properties
public bool CancellingEnabled
{
get
{
return btnCancel.IsVisible;
}
set
{
btnCancel.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
}
}
public bool Cancelled
{
get
{
return m_isCancelled;
}
}
public bool AutoIncrement
{
get
{
return (bool)this.GetValue(AutoIncrementProperty);
}
set
{
this.SetValue(AutoIncrementProperty, value);
}
}
public Exception Error
{
get
{
return m_error;
}
}
#endregion
#region Public Methods
public void Run(Action<IProgressContext> action)
{
if (AutoIncrement)
{
progressBar.IsIndeterminate = true;
}
//store the UI culture
m_culture = CultureInfo.CurrentUICulture;
//store reference to callback handler and launch worker thread
m_workerCallback = action;
m_worker.RunWorkerAsync();
//display modal dialog (blocks caller)
ShowDialog();
}
#endregion
#region Private Methods
#region Event Handlers
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
//make sure the UI culture is properly set on the worker thread
Thread.CurrentThread.CurrentUICulture = m_culture;
ProgressContext context = new ProgressContext((BackgroundWorker)sender);
//invoke the callback method with the designated argument
m_workerCallback(context);
}
catch (Exception)
{
//disable cancelling and rethrow the exception
Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(SendOrPostCallback)delegate { btnCancel.SetValue(Button.IsEnabledProperty, false); },
null);
throw;
}
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
btnCancel.IsEnabled = false;
m_worker.CancelAsync();
m_isCancelled = true;
}
private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage != int.MinValue)
{
progressBar.Value = e.ProgressPercentage;
}
if (e.UserState != null)
{
lblStatus.Text = (string)e.UserState;
}
}
private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
m_error = e.Error;
}
//update UI in case closing the dialog takes a moment
btnCancel.IsEnabled = false;
Close();
}
#endregion
#endregion
}
public class ProgressContext : MarshalByRefObject, IProgressContext
{
#region Fields
private BackgroundWorker m_worker;
#endregion
#region Constructors
public ProgressContext(BackgroundWorker worker)
{
m_worker = worker;
}
#endregion
#region Public Properties
public void ReportProgress(string message)
{
m_worker.ReportProgress(int.MinValue, message);
}
public void ReportProgress(int progress, string message)
{
m_worker.ReportProgress(progress, message);
}
public void ReportProgress(int progress)
{
m_worker.ReportProgress(progress);
}
public bool IsCancelled
{
get
{
return m_worker.CancellationPending;
}
}
#endregion
}
任何幫助將不勝感激。提前致謝。
在這裏使用的遠程處理需要更多的細節(可能是代碼)。 – Nayan
嘗試使用Dispatcher類和DispatcherPriority.Background來設置progressBar值。 – vorrtex
不幸的是,我不能提供服務器端操作執行的詳細代碼,因爲他們需要數千行。遠程設置沒有什麼特別的,在任何情況下都能很好地工作。問題不會立即發生。進度報告,然後過了一段時間,重度行動來了 - 用戶界面卡住了。如果有什麼事情導致這種行爲,我會很高興檢查。謝謝。 – Amid