Backgroundworker 阻止页面加载
Backgroundworker blocks Pageload
我正在尝试从 Entity Framework 加载大量数据。该请求大约需要一分钟,并会阻止页面加载。由于这对于较大的查询变得不合理,我想我会尝试使用后台线程或类似的东西。经过一段时间的研究,我发现了一个叫做 BackgroundWorker 的东西。我试图实现这一点,但它不起作用。
这是我的代码:
void Page_LoadComplete(object sender, EventArgs e)
{
InitializeBackgroundWorker();
}
private void InitializeBackgroundWorker()
{
bw = new BackgroundWorker {WorkerReportsProgress = true};
bw.DoWork += (sender, e) => e.Result = (List<object>)e.Argument;
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerAsync(doSomething());
bw.RunWorkerCompleted += (sender, e) =>
{
AjaxWaitBox.Text = "Completed";
};
}
private readonly Func<List<object>> doSomething = () =>
{
var list = ObjectFactory.Container.GetInstance<IActivityRepository>().GetAllActivitiesNotFiltered(ContentReference.RootPage);
var count = list.Count;
int i = 0;
foreach (var item in list)
{
i++;
Console.WriteLine("-(DoWork)->" + i);
double percentage = (Convert.ToDouble(i) / Convert.ToDouble(count)) * 100;
Console.WriteLine("-(DoWork.percentage)-> " + percentage);
bw.ReportProgress((int)percentage);
}
return list;
};
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
AjaxWaitBox.Text = e.ProgressPercentage.ToString();
}
起初我在 OnInit 方法中调用了 InitializeBackgroundWorker()。然后页面加载了大约一分钟,然后用于显示查询进度的文本框的值为:"completed"。然后我将呼叫移至 Page_LoadComplete 但结果仍然相同。我在这里错过了什么?我还需要包含 async/await 运算符还是什么?
您正在同步调用 doSomething()。
你应该这样做(未测试):
private void InitializeBackgroundWorker()
{
System.ComponentModel.BackgroundWorker bw = new System.ComponentModel.BackgroundWorker { WorkerReportsProgress = true };
bw.DoWork += (sender, e) => e.Result = doSomething();
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerAsync();
bw.RunWorkerCompleted += (sender, e) =>
{
AjaxWaitBox.Text = "Completed";
};
}
BackgroundWorker
仅对释放 UI 线程有用。由于您在 ASP.NET,您没有 UI 话题。
ASP.NET 适用于 HTTP 请求和响应。 "page" 抽象(不幸的是) 看起来 像一个 UI 框架,但它 不是 。
因此,您需要根据 HTTP 请求和响应来考虑您的问题,因为这是实际发生的事情。每个请求只有一个响应,因此无法 "send a page-without-data response" 然后 将其 更改为 "send a page-with-data response".
相反,您要做的是发送一个没有数据的页面响应,然后让该页面使用 AJAX(或 UpdatePanel
)之类的技术发出单独的请求实际数据并用它填写页面。
我正在尝试从 Entity Framework 加载大量数据。该请求大约需要一分钟,并会阻止页面加载。由于这对于较大的查询变得不合理,我想我会尝试使用后台线程或类似的东西。经过一段时间的研究,我发现了一个叫做 BackgroundWorker 的东西。我试图实现这一点,但它不起作用。 这是我的代码:
void Page_LoadComplete(object sender, EventArgs e)
{
InitializeBackgroundWorker();
}
private void InitializeBackgroundWorker()
{
bw = new BackgroundWorker {WorkerReportsProgress = true};
bw.DoWork += (sender, e) => e.Result = (List<object>)e.Argument;
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerAsync(doSomething());
bw.RunWorkerCompleted += (sender, e) =>
{
AjaxWaitBox.Text = "Completed";
};
}
private readonly Func<List<object>> doSomething = () =>
{
var list = ObjectFactory.Container.GetInstance<IActivityRepository>().GetAllActivitiesNotFiltered(ContentReference.RootPage);
var count = list.Count;
int i = 0;
foreach (var item in list)
{
i++;
Console.WriteLine("-(DoWork)->" + i);
double percentage = (Convert.ToDouble(i) / Convert.ToDouble(count)) * 100;
Console.WriteLine("-(DoWork.percentage)-> " + percentage);
bw.ReportProgress((int)percentage);
}
return list;
};
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
AjaxWaitBox.Text = e.ProgressPercentage.ToString();
}
起初我在 OnInit 方法中调用了 InitializeBackgroundWorker()。然后页面加载了大约一分钟,然后用于显示查询进度的文本框的值为:"completed"。然后我将呼叫移至 Page_LoadComplete 但结果仍然相同。我在这里错过了什么?我还需要包含 async/await 运算符还是什么?
您正在同步调用 doSomething()。 你应该这样做(未测试):
private void InitializeBackgroundWorker()
{
System.ComponentModel.BackgroundWorker bw = new System.ComponentModel.BackgroundWorker { WorkerReportsProgress = true };
bw.DoWork += (sender, e) => e.Result = doSomething();
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerAsync();
bw.RunWorkerCompleted += (sender, e) =>
{
AjaxWaitBox.Text = "Completed";
};
}
BackgroundWorker
仅对释放 UI 线程有用。由于您在 ASP.NET,您没有 UI 话题。
ASP.NET 适用于 HTTP 请求和响应。 "page" 抽象(不幸的是) 看起来 像一个 UI 框架,但它 不是 。
因此,您需要根据 HTTP 请求和响应来考虑您的问题,因为这是实际发生的事情。每个请求只有一个响应,因此无法 "send a page-without-data response" 然后 将其 更改为 "send a page-with-data response".
相反,您要做的是发送一个没有数据的页面响应,然后让该页面使用 AJAX(或 UpdatePanel
)之类的技术发出单独的请求实际数据并用它填写页面。