编辑:到了某个地方,我希望
这就是我所拥有的,但我不太确定如何将我的bcLoad.ReportProgress(i)委托给创建的对象(即如何制作委托以便可以传递)。我已经创建了有效的对象事件(我可以调用我的对象方法,我可以看到在读取行时触发的更改)。我知道objectChanged何时工作(写入控制台)。但是,bcLoad_RunWorkerCompleted似乎不起作用,if语句中的代码永远不会执行,所以我在某处出错了。文件加载了。
有人可能请说明如何创建委托,然后使用传递委托的哪个部分(我假设在对象中)以及为什么bcLoad_RunWorkerComplete为null。 这是我第一次在c#
中使用事件,代表和背景工作者/*
The object which does file operations
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;
using System.Windows.Forms;
using System.ComponentModel;
using System.Data;
namespace aodProductionViewer
{
public class fileOperationsSpecial
{
public event EventHandler Changed;
protected virtual void OnChanged(EventArgs e)
{
if (Changed != null)
{
Changed(this, e);
}
}
public fileOperationsSpecial()
{ }
/// <summary>
/// Count the number of lines in the file specified.
/// </summary>
/// <param name="f">The filename to count lines in.</param>
/// <returns>The number of lines in the file.</returns>
static long CountLinesInFile(string f)
{
long count = 0;
try
{
using (StreamReader r = new StreamReader(f))
{
string line;
while ((line = r.ReadLine()) != null)
{
count++;
}
}
}
catch (Exception err)
{
string strTemp = "Error get number of lines for save game file. \n" +
err.ToString();
errorDialog errDiag = new errorDialog("save game line count",
strTemp, true);
}
return count;
}
/// <summary>
/// Use this to readin in a file
/// </summary>
/// <param name="strPath">Path of file to read in</param>
/// <returns>a string array of the file</returns>
public string[] readFile(string strPath)
{
long lng_LineCount = CountLinesInFile(strPath);
string[] strReadIn = new string[lng_LineCount];
try
{
long lngCount = 0;
using (StreamReader reader = new StreamReader(strPath))
{
String line;
while ((line = reader.ReadLine()) != null)
{
strReadIn[lngCount] = line;
lngCount++;
OnChanged(EventArgs.Empty);
}
}
}
catch (Exception err)
{ //
}
return strReadIn;
}
}
}
/*
Event Listner
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace aodProductionViewer
{
class EventListener
{
private fileOperationsSpecial FPS;
public EventListener(fileOperationsSpecial _fps)
{
FPS = _fps;
FPS.Changed += new EventHandler(objectChanged);
}
private void objectChanged(object sender, EventArgs e)
{ //changed has occured
}
public void Detach()
{
FPS.Changed -= new EventHandler(objectChanged);
FPS = null;
}
}
}
/*
The backgroundWorker code (Part of)
*/
BackgroundWorker bcLoad = new BackgroundWorker();
private void btt_load_save_game_Click(object sender, EventArgs e)
{
//Do some file dialog stuff
string strPath = null;
bcLoad.RunWorkerAsync(strPath);
}
void bcLoad_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
tb_ProgressBar.Value = e.ProgressPercentage;
}
void bcLoad_DoWork(object sender, DoWorkEventArgs e)
{
string strPath = e.Argument as string;
fileOperationsSpecial FPS = new fileOperationsSpecial();
EventListener listener = new EventListener(FPS);
string strArray = FPS.readFile(strPath);
listener.Detach();
}
void bcLoad_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Result != null)
{
//Everything done
tb_ProgressBar.Visible = false;
}
}
我已经掌握了使用BackgroundWorker做一些工作并更新UI进度和完成的要点,我现在有一些简单的东西正如你所看到的,我传递一个字符串(这是一个路径)然后我会读取一个文件并更新进度,目前我只是在休眠线程并为演示设置进度。我还打算返回一个对象(字符串数组),但我还没有解决这个问题。
现在我的问题是,如何在我的表单创建的对象中完成所有这些操作并仍然更新我的UI?我有一个目前对文件进行操作的对象(即读取文件,写入,获取信息)。
目前我的理解是下面的演示
表格&gt;
我希望它去
表格&gt;创建对象&gt;
我看过并且没有做过任何一个例子的正面或反面,所以我想我会问那些会知道的人。这甚至可能吗?我想要的目标是从我的表单中删除任何文件处理,以便管理和维护变得更容易。
如何执行此操作的完整代码示例非常棒!
这是我到目前为止所理解的(记住只是为了一个例子,这不会编译)
BackgroundWorker bcLoad = new BackgroundWorker();
public frm_ProductionViewer()
{
InitializeComponent();
load_settings();
bcLoad.DoWork += new DoWorkEventHandler(bcLoad_DoWork);
bcLoad.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bcLoad_RunWorkerCompleted);
bcLoad.WorkerReportsProgress = true;
bcLoad.ProgressChanged += new ProgressChangedEventHandler(bcLoad_ProgressChanged);
bcLoad.WorkerSupportsCancellation = true;
}
private void btt_load_save_game_Click(object sender, EventArgs e)
{
ts_label_GameLoaded.Text = "Loading";
bcLoad.RunWorkerAsync(strPath);
}
void bcLoad_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
tb_ProgressBar.Value = e.ProgressPercentage;
}
void bcLoad_DoWork(object sender, DoWorkEventArgs e)
{
string strPath = e.Argument as string;
//load file
//Update progress
bcLoad.ReportProgress(80);
Thread.Sleep(300 * 5);
bcLoad.ReportProgress(100);
}
void bcLoad_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Result != null)
{
textBox1.Text = "done";
}
tb_ProgressBar.Visible = false; ;
ts_label_GameLoaded.Text = "Loaded";
}
答案 0 :(得分:3)
您的对象(使用文件)最好不要依赖于GUI或Bgw。
因此,请将您的Bgw与(在)表单上保持一致,然后调用对象表单DoWork。
要报告反馈,您的对象需要一个事件(或采用委托参数的主要方法)。
在该事件的处理程序中(在工作线程上调用),调用bcLoad.ReportProgress(百分比)。
对编辑的反应:
您需要一个具有百分比空间的EventArgs类型,如EventHandler<ProgressEventArgs>
,您可能需要编写ProgressEventArgs。
我认为你不想要一个单独的EventListener类。这是Forms工作。这会让你:
class Form ...
{
private void objectChanged(object sender, ProgressEventArgs e)
{ //changed has occured
// trigger the Bgw event
// or use Form.Invoke here to set the progress directly
bcLoad.ReportProgress(e.Percentage);
}
}
所以'更改'现在过滤了2个事件处理程序。 1打破FPS的依赖,1同步到Form。
答案 1 :(得分:0)
如果您希望某个类(表单除外)封装后台工作程序,则一种方法是向该类添加一个事件并在表单中订阅此事件: