每分了,跪求关于线程全局变量问题

buduanxuexi 2010-11-15 01:47:46
我现在做一个串口编程项目,思路如下:

程序一启动则启动两个异步操作,由于串口同一时刻只能一个线程往里面写入东西,所以用到了一个全局变量IsAvailable,来标识当前串口是否空闲,现在就是在读取这个参数时有冲突,导致两个任务同时在操作,具体代码如下:

1.程序开启时
/// <summary>
/// 启动服务程序
/// </summary>
private void StartServer()
{


// 获取串口号列表
cdts = new BLLM_Cdt().GetModelList(string.Empty);
IList<string> comms = new List<string>();
foreach (M_Cdt model in cdts)
{
if (!comms.Contains(model.Comm.ToString()))
{
comms.Add(model.Comm.ToString());
}
}

// 初始化串口实例
foreach (string comm in comms)
{
SerialPortUnit serialPort = new SerialPortUnit("COM"+comm);
Task pCI = new Task();
pCI.PortNum = DataTypeHelper.GetInt(comm);
pCI.SPUnit = serialPort;

NewTaskDelegate pInitTime = new NewTaskDelegate(InitTime);
IAsyncResult pInitTimeResult = pInitTime.BeginInvoke(pCI, null, null);

NewTaskDelegate pSetOpenTime = new NewTaskDelegate(SetOpenTime);
IAsyncResult pSetOpenTimeResult = pSetOpenTime.BeginInvoke(pCI, null, null); }

#endregion
}

=======================================InitTime方法体=========================================================

/// <summary>
///
/// </summary>
/// <param name="details"></param>
void InitTime(Task pCI)
{
#region

if (pCI != null)
{
while (bStart)
{
if (pCI.PortNum != null)
{
// 等待通道可利用
while (!pCI.IsAvailable)
{
Thread.Sleep(1000 * Config.SendInterval);
}
pCI.IsAvailable = false;

// 执行其他方法内容
。。。。。。

pCI.IsAvailable = true;
}
Thread.Sleep(1000 * Config.InitReadPlanInterVal);
}
}

#endregion
}

==============================SetOpenTime方法体========================================================

/// <summary>
/// 设置定时时间
/// </summary>
void SetOpenTime(Task pCI)
{
#region

if (pCI != null)
{
while (bStart)
{
if (pCI.PortNum != null)
{
// 等待通道可利用
while (!pCI.IsAvailable)
{
Thread.Sleep(1000 * Config.SendInterval);
}
pCI.IsAvailable = false;

// 执行其他方法内容
。。。。。。

pCI.IsAvailable = true;
}
Thread.Sleep(1000 * Config.InitControlPlanInterVal);
}
}

#endregion
}


==================================Task结构体========================================================
/// <summary>
/// 抄表任务
/// </summary>
public class Task
{
/// <summary>
/// 串口号
/// </summary>
public int? PortNum=null;

/// <summary>
/// 串口对象类
/// </summary>
public SerialPortUnit SPUnit;

/// <summary>
/// 计划从表
/// </summary>
public IList<M_PlanDetail> PlanDetails;

/// <summary>
/// 实时抄表计划
/// </summary>
public IList<M_RealTimePlan> M_RealTimePlans;

Mutex mutex = new Mutex();
object syncIsRunReal = new object();
object syncIsAvailable = new object();
bool isRunReal = false;
public bool isAvailable = true;

/// <summary>
/// 是否有实时抄表计划
/// </summary>
public bool IsRunReal
{
get
{
mutex.WaitOne();
return isRunReal;
mutex.ReleaseMutex();
}
set
{
mutex.WaitOne();
isRunReal = value;
mutex.ReleaseMutex();
}
}


/// <summary>
/// 广播校时时间:00:10:00
/// 当校时完毕后修改广播校时时间为下一天的00:10:00
/// </summary>
public DateTime BroadCastTime = PublicBasis.DataTypeHelper.GetDateTime(DateTime.Now.ToString("yyyy-MM-dd 00:10:00"));

/// <summary>
/// 下次读表时间,此时间是后台定时轮训时间
/// 和抄表计划中的时间不同
/// </summary>
public DateTime NextTime = DateTime.Now;

/// <summary>
/// 下次轮训报警时间
/// </summary>
public DateTime NextCheckWaringTime = DateTime.Now;

/// <summary>
/// 下次初始化表具时间
/// </summary>
public DateTime NextInitTime = DateTime.Now;

/// <summary>
/// 下次下发控制命令时间
/// </summary>
public DateTime NextSetOpenTime = DateTime.Now;




/// <summary>
/// 串口是否可用
/// </summary>
public bool IsAvailable
{
get
{
lock (syncIsAvailable)
{
return isAvailable;
}
}
set
{
lock (syncIsAvailable)
{
isAvailable = value;
}
}
}

/// <summary>
/// 当前抄码对象
/// </summary>
public CurrPlanDetail CurrPlanDetail;

/// <summary>
/// 当前实时抄码对象
/// </summary>
public CurrM_RealTimePlan currM_RealTimePlan;

/// <summary>
/// 初始化CurrPlanDetail
/// </summary>
/// <returns></returns>
public CurrPlanDetail InitCurrPlanDetail(M_PlanDetail model)
{
CurrPlanDetail cpd = new CurrPlanDetail();
PublicBasis.DataTypeHelper.Clone(cpd.planDetail, model);
return cpd;
}

/// <summary>
/// 初始化CurrM_RealTimePlan
/// </summary>
/// <returns></returns>
public CurrM_RealTimePlan InitCurrM_RealTimePlan(M_RealTimePlan model)
{
CurrM_RealTimePlan cpd = new CurrM_RealTimePlan();
PublicBasis.DataTypeHelper.Clone(cpd.M_RealTimePlan, model);
return cpd;
}

/// <summary>
///
/// </summary>
public List<M_PlanDetail> details;

public List<M_ControlPlanDetail> M_ControlPlanDetails;
}

现在两个方法经过测试,都有可能同时到达红色的部分,导致程序打架,请问如何控制可以解决该问题。
// 等待通道可利用
while (!pCI.IsAvailable)
{
Thread.Sleep(1000 * Config.SendInterval);
}
pCI.IsAvailable = false;
...全文
118 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
pcqpzq 2010-11-15
  • 打赏
  • 举报
回复
何况这么麻烦,直接加锁就行了
lock(object)
兔子-顾问 2010-11-15
  • 打赏
  • 举报
回复
串口支持异步读写。

110,535

社区成员

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

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

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