在后台工作线程中运行类方法时,如何以不同的形式重用类
本文关键字:线程 工作 后台 运行 类方法 | 更新日期: 2023-09-27 18:33:01
我在 Form1 中有这个功能,效果很好。这个想法是从大的xml文件中检索一些文本。因此,在 Form1 构造中,我做到了:
r = new StreamReader(@"D:'Deponia_Work'Deponia Extracted Files'000004aa.xml");
f = r.ReadToEnd();
r.Close();
变量 f 是字符串。
现在我在 Form1 中有了这个函数,我称之为 test((,它正在从大的 000004aa.xml 文件中检索/提取文本。
private void test()
{
int countFiles = 0;
byte[] a;
string startTag = "T256='"";
string endTag = "'"";
int index = 0;
int startTagWidth = startTag.Length;
int endTagWidth = endTag.Length;
int fileLength = f.Length;
w = new StreamWriter(@"d:'testingdeponias.txt");
while (true)
{
if (index > f.LastIndexOf(startTag))
{
break;
}
int startTagIndex = f.IndexOf(startTag, index);
int stringIndex = startTagIndex + startTagWidth;
index = stringIndex;
int endTagIndex = f.IndexOf(endTag, index);
int stringLength = endTagIndex - stringIndex;
if (stringLength == 0)
{
}
else
{
string test = f.Substring(stringIndex, stringLength);
if (test.Contains("<pa>"))
{
string t = "<pa>";
int y = t.Length;
string test1 = test.Substring(0, stringLength - y);
listBox1.Items.Add(test1);
w.WriteLine(test1);
}
//else
// {
listBox1.Items.Add(test);
w.WriteLine(test);
// }
}
}
w.Close();
}
然后,我在 Form1 中添加了一个新的 backgroudnworker2 事件:
这是DoWork事件:
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker2 = sender as BackgroundWorker;
lists1.extractTextDeponia(worker2, backgroundWorker2, listBox1, textBox1,f, w, e);
}
这是我启动后台工作者的按钮单击事件:
private void button8_Click(object sender, EventArgs e)
{
backgroundWorker2.RunWorkerAsync();
}
在新类中,我创建了一个新的函数公共函数,该函数从 Form1 获取一些变量。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Web;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
namespace List_Words
{
class Lists
{
public void List_Words()
{
}
public void extractTextDeponia(BackgroundWorker worker, BackgroundWorker backgroundWorker2, ListBox lbox , TextBox tbox , StreamWriter streamW , string read, DoWorkEventArgs e)
{
我的问题是如何更改 test(( 函数并将其从 Form1 转换为新类到新函数,以便它也可以与后台工作者 2 一起使用?
我尝试在那里使用/添加 FileStream 并添加了 while 循环,它将逐行读取,但它效果不佳。
** 这是带有函数的新类,它不像 Form1 中的 test(( 那样起作用
**using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Web;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
namespace List_Words
{
class Lists
{
public void List_Words()
{
}
public void extractTextDeponia(BackgroundWorker worker, BackgroundWorker backgroundWorker2, ListBox lbox , TextBox tbox , StreamWriter streamW , string read, DoWorkEventArgs e)
{
string startTag = "T256='"";
string endTag = "'"";
int index = 0;
int startTagWidth = startTag.Length;
int endTagWidth = endTag.Length;
int fileLength = read.Length;
using (var fs = new FileStream(@"D:'Deponia_Work'Deponia Extracted Files'000004aa.xml", FileMode.Open, FileAccess.Read))
{
using (var h = new StreamReader(fs))
{
string line;
line = h.ReadLine();
while ((line = h.ReadLine()) != null)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
int percent = (int)(fs.Position * 100 / fs.Length);
backgroundWorker2.ReportProgress(percent);
if (index > read.LastIndexOf(startTag))
{
break;
}
int startTagIndex = read.IndexOf(startTag, index);
int stringIndex = startTagIndex + startTagWidth;
index = stringIndex;
int endTagIndex = read.IndexOf(endTag, index);
int stringLength = endTagIndex - stringIndex;
if (stringLength == 0)
{
}
else
{
line = read.Substring(stringIndex, stringLength);
if (line.Contains("<pa>"))
{
string t = "<pa>";
int y = t.Length;
string test1 = line.Substring(0, stringLength - y);
if (lbox.InvokeRequired)
{
lbox.Invoke(new MethodInvoker(delegate { lbox.Items.Add(test1); }));
}
//w.WriteLine(test1);
line = h.ReadLine();
if (tbox.InvokeRequired)
{
tbox.Invoke(new MethodInvoker(delegate { tbox.Text = test1; }));
}
}
//else
// {
if (lbox.InvokeRequired)
{
lbox.Invoke(new MethodInvoker(delegate { lbox.Items.Add(line); }));
}
//w.WriteLine(line);
if (tbox.InvokeRequired)
{
tbox.Invoke(new MethodInvoker(delegate { tbox.Text = line; }));
}
// }
}
}
}
}
}
streamW = new StreamWriter(@"d:'testingdeponias.txt");
streamW.AutoFlush = true;
streamW.Write(read);
streamW.Close();
}
}
}
在形式 1 中,我将其称为:
BackgroundWorker worker2 = sender as BackgroundWorker;
lists1.extractTextDeponia(worker2, backgroundWorker2, listBox1, textBox1,w, f, e);
w 是流写入器 f 是字符串,e 是 backgroundowrker2 DoWork e 变量正如我上面所示,我在 Form1 构造函数中使用 f 来读取大的 xml 文件,但我也在新类中执行此操作并使用 FileStream 函数,真是一团糟。**
有一件事可能会有所帮助,那就是稍微改变一下你的编程思维方式。 与其考虑窗体和事件,不如考虑这些数据实体上的数据实体和操作,然后可以使用服务类型模式。
因此,您要做的是创建一个服务类,它可以执行您想要发生的任何事情。 由于您使用的是后台工作线程,因此我会将其创建为实例类而不是静态。
public class FileWorkerService
{
private BackgroundWorker _worker;
public FileWorkerService()
{
_worker = new BackgroundWorker();
}
public void ReadFileAndProcessIt()
{
if (!_worker.IsBusy)
{
_worker.RunWorkerAsync();
}
}
}
现在,只需像以前对事件所做的那样连接_worker,您的服务类就可以开始工作了。
为了让它做某事,您只需创建它的实例并调用启动工作线程的函数。
因此,在您的表单按钮单击上,您将拥有...
private void button8_Click(object sender, EventArgs e)
{
var newService = new FileWorkerService();
newService.ReadFileAndProcessIt();
}
================= 编辑 ========================================-- 添加了如何从服务内更新后台工作进程的进度。 <<<===
==============================================================
在 FileWorkerService 类中
public void SetWorkerProgress(int currentValue)
{
_worker.ReportProgress(currentValue);
}
在课堂外打电话,从你的主表格,你会做...
newService.SetWorkerProgress(whatever);