多线程调用dll,时不时出错

natfit 2010-08-20 09:58:18
我调用一个验证码识别程序的dll来识别电话,同时开5个线程,不时地出错,并且停止全部线程及其父线程后,并sleep 200秒,再次调用,大部分时候还是出错!

调用代码:

hftClass.pic picc = new hftClass.pic();


err = picc.getPicWord(para, ref root, ref urlRef, ref val);

picc.Dispose();

picc = null;

picc:

public class pic : IDisposable
{

下面两个函数是调用验证码的
[DllImport("ycode.dll")]
public static extern int loadcode(int code, int Length, IntPtr address, IntPtr pass);
[DllImport("ycode.dll")]
public static extern IntPtr Recognitiond(int ItemNo, int picin, int Length, IntPtr Address1, IntPtr Address2);


取电话号码
public Pub.errCode getPicWord(string[] para, ref string root, ref string urlref, ref string tel)
{

string tel101 = "";
string[] urlpic = new string[0];


int ii = 0;




if (para[1] == "")
{
//用con取
urlpic = para[0].Split("‖".ToCharArray());

}
else
{
MatchCollection mc101 = hString.getMatchs(para[0], para[1]);

if (mc101 != null)
{
urlpic = new string[mc101.Count];

for (int i = 0; i < mc101.Count; i++)
{
for (int j = 1; j < mc101[i].Groups.Count; j++)
{
if (mc101[i].Groups[j].Value != "")
{
urlpic[i] = mc101[i].Groups[j].Value;

}
}
}
}
}

bool recoge = true;

//先下载图片到本地
for (int ij = 0; ij < urlpic.Length; ij++)
{
if (urlpic[ij] == "")
continue;

urlpic[ij] = hWeb.Href.makeHref(urlpic[ij], root, urlref);

urlpic[ij] = hWeb.WebDbo.getHttpPicFile(urlpic[ij], urlref);

recoge = recoge & (!string.IsNullOrEmpty(urlpic[ij]));

}

if (!recoge) //如果一个也没有取到
{
return Pub.errCode.图片文件不存在;
}
//else
//{
// System.Windows.Forms.Application.DoEvents();//
// //System.Threading.Thread.Sleep(200);
//}

try
{

用不用lock都一样
object obj = new object();

lock (obj)
{

IntPtr ipPath = Marshal.StringToHGlobalAnsi(para[3]);
IntPtr ipPass = Marshal.StringToHGlobalAnsi(para[4]);



大部分错误在此,因为调用的识别验证码文件库一致,dll文件也一致,就在此处出错,错误:

尝试读取或写入受保护的内存。这通常指示其他内存已损

我不知道这个dll是不是多线程安全的。

但在服务器上(8核,intel),这种现象就很少,同样是开5个线程。而在我的机器上(2核,AMD),就容易出问题,最主要的是,出问题后错误清除不了,会一直错下去,我不知道是什么原因,请各位大侠指点!



ii = loadcode(0, 0, ipPath, ipPass);

if (ii != 1)
{
Pub.errDes err = new Pub.errDes();
err.errType = Pub.errMode.Data;
err.errPage = "Method";
err.errFun = "getPicWord";
err.errMes = "打开识别库失败";



Pub.writeErr(err);
//Pub.writeErr(Pub.errMode.Scan, "Method", "getPicWord", "打开识别库失败", "");



return Pub.errCode.打开识别库失败;

}


for (int ij = 0; ij < urlpic.Length; ij++)
{
if (urlpic[ij] == "")
continue;

// urlpic[ij] = hWeb.Href.makeHref(urlpic[ij], root, urlref);


IntPtr ptrIn = Marshal.StringToHGlobalAnsi(urlpic[ij]);

string tttt = "";

IntPtr ptrFile = Marshal.StringToHGlobalAnsi(tttt);

IntPtr no1 = Recognitiond(1, 0, 0, ptrFile, ptrIn);//取文字识别指针


tel101 = Marshal.PtrToStringAnsi(no1);


if (tel101 != "")
{

if (tel101.IndexOf("?") < 0)
{
if (tel == "")
{
tel = tel101;
}
else
{
if (tel.IndexOf(tel101) < 0)
{
tel = tel + "‖" + tel101;
}
}
}
}
}
}


return Pub.errCode.完成;
}
catch (Exception ee)
{
Pub.errDes err = new Pub.errDes();
err.errType = Pub.errMode.Error;
err.errPage = "Method";
err.errFun = "getPicWord";
err.errMes = ee.Message;
err.errOther = urlref;



Pub.writeErr(err);

if (ee.Message.IndexOf("尝试读取或写入受保护的内存") > -1)
{


我在此控制,停止所有线程,置其父线程为null,并在最上级线程中,用timer进行再次启动

return Pub.errCode.需要重启;
// return Pub.errCode.完成;

}
else
{
// Pub.writeErr(Pub.errMode.Scan, "Method", "getPicWord", ee.Message, urlref);
//return Pub.errCode.未取到电话;
return Pub.errCode.完成;
}
}


}

public void Dispose()
{
GC.SuppressFinalize(this);
}
}


连续三次出错后,我会清除他们的父线程:

public void Dispose()
{
if (Pub.intTh > 0)
{
//说明还有线程在工作,就不能关闭

Pub.bEnd = true;
int i = 0;
while (Pub.intTh > 0)
{

//Pub.strGetNow = "正在结束进程,请稍候!!!" ;
// Application.DoEvents();
Thread.Sleep(2000);
i++;

if (i > 99)//强制关掉
break;
}

}


if (thTimer != null)
{
thTimer.Dispose();
thTimer = null;
}

if (dtScan != null)
{
dtScan.Dispose();
dtScan = null;
}

bDoing = false;


alive = false;


tha = null;

GC.SuppressFinalize(this);
}


再在上级线程中:

先清除包含子线程的类实例th(线程在类实例th中启动)

if (th != null)
{
if (th.alive == true)
{
//检查循环是否还在继续
if (th.lastDone.AddMinutes(10) < DateTime.Now)
{
//说明很长时间没有循环了

bDoing = true;

th.Dispose();

th = null;

Thread.Sleep(200000); //等待200秒, 不知道是不是这个时间不够


}
else
{
return;
}
}
else
{
bDoing = true;

th.Dispose();

th = null;

Thread.Sleep(200000);


}
}

再重新开
Pub.bEnd = false;

th = new thclass2();



  请各位对dll调用比较熟练的大侠指点!



...全文
616 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
Jason-Jin 2011-06-16
  • 打赏
  • 举报
回复
我也遇到这个问题了
请问最后如何解决
jihure 2010-12-08
  • 打赏
  • 举报
回复
调用DLL之后线程延时一下试试
natfit 2010-08-20
  • 打赏
  • 举报
回复
调用dll后,下面还有很多工作,本身不会马上就执行的。但另外的线程就会同时执行
natfit 2010-08-20
  • 打赏
  • 举报
回复
Help
lzhzxl 2010-08-20
  • 打赏
  • 举报
回复
调用DLL之后线程延时一下试试
natfit 2010-08-20
  • 打赏
  • 举报
回复
就是锁死了,为什么子线程重新启动后(3、4分钟后),还是会连续报错呢。

它是个服务,服务启动一个线程1,该线程再打开一个类实例,在实例中再启动一个线程2,然后在这个线程中再开5个线程3。

出错后,我会逐级关闭线程,直到最顶层的线程1,然后再重新打开类实例,开新线程2,但还是会继续错误。

好象是关闭线程并不能完全释放资源!

出错无所谓,但不能重新启动就要命了
g394594141 2010-08-20
  • 打赏
  • 举报
回复
具体怎么解决我不太清楚。但是你说的


用不用lock都一样
object obj = new object();

lock (obj)

你这里的代码lock的是个局部变量,肯定是一样的,要不你把obj提到外面,要不你用Moniter控制线程的异步试试
natfit 2010-08-20
  • 打赏
  • 举报
回复
ii = loadcode(0, 0, ipPath, ipPass);

有时候也会在这儿返回 无法调用成功,但不会进到catch里面报错
natfit 2010-08-20
  • 打赏
  • 举报
回复
各位继续啊

110,535

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧