小应用程序中的线程同步
我有以下问题。我完成了我的申请,哪一个做某事。同时一些代码(绘制图表并将数据保存到日志文件)可以由几个线程使用。我无法同步这些线程的保存数据。有一些例外情况,即文件正在被其他进程使用。在 form1.cs 文件上,我正在启动此线程,这些线程正在另一个文件(charts.cs)上启动函数。
form1.cs 文件的一部分:
UserControl1 us = ctrl as UserControl1;
us.newThread = new Thread(new ThreadStart(us.wykres.CreateChart));
us.newThread.Start();
charts.cs 文件:
public class Charts
{
private StreamWriter sw = new StreamWriter("logFile.txt", true);
static readonly object LogLock = new object();
private ZedGraphControl zzz;
public ZedGraphControl ZZZ
{
get { return zzz; }
set { zzz = value; }
}
private UserControl1 uc1;
public UserControl1 Uc1
{
get { return uc1; }
set { uc1 = value; }
}
//jakiś kod
void WriteLog(string wpis, StreamWriter streamW)
{
lock (LogLock)
{
streamW.WriteLine(wpis);
streamW.Flush();
}
}
public void CreateChart()
{
try
{
//tutaj znów jakiś kod
//poniżej najważniejsza
while ()
{
if ()
{
if (go == false)
{
ZZZ.Invoke(Uc1.warnDelegate, "Osiągnięto strefę bezpiecznych wartości");
}
wpis = "jakis string";
WriteLog(wpis, sw);
wpis = null;
}
if ()
{
if ()
{
ZZZ.Invoke(Uc1.warnDelegate, "Osiągnięto strefę 1");
}
wpis = "jakis string";
WriteLog(wpis, sw);
wpis = null;
}
else if ()
{
if ()
{
ZZZ.Invoke(Uc1.warnDelegate, "Osiągnięto strefę 2");
}
wpis = "jakis string";
WriteLog(wpis, sw);
wpis = null;
}
//jakiś kod odnośnie rysowania wykresow
ZZZ.Invoke(Uc1.myDelegate);
Thread.Sleep(odstepCzasu * 1000);
}
}
catch (InvalidOperationException e)
{
MessageBox.Show(e.Message);
}
catch (ThreadAbortException)
{
}
}
}
}
userControl1.cs 文件的一部分:
public delegate void RefreshDelegate();
public delegate void ShowWarningDialogDelegate(string aaa, string bbb, string ccc);
public RefreshDelegate myDelegate;
public ShowWarningDialogDelegate warnDelegate;
public Thread newThread = null;
public Charts wykres = null;
public UserControl1()
{
InitializeComponent();
wykres = new Charts();
wykres.ZZZ = zedGraphControl1;
wykres.Uc1 = this;
myDelegate = new RefreshDelegate(wykres.ZZZ.Refresh);
warnDelegate = new ShowWarningDialogDelegate(minDelegate);
}
private void minDelegate(string strLabel1, string strLabel2)
{
WarningForm forma = new WarningForm(strLabel1, strLabel2);
forma.Show();
}
您能否向我展示如何同步它,以使多个线程同时访问日志文件(当它们想要保存某些内容时)?我听说这是典型的生产者-消费者问题,但我不知道如何在我的案例中使用它。如果有任何停顿,我将非常感激。问候。
I have the following problem. I finishing my application, which one do something. Simultaneously some code (drwaing charts and save data to log file) can be using by a few threads. I can't synchornize save data which those threads. There is some exception that file is using by other process. On form1.cs file I'm starting this threads, which are starting function on another file (charts.cs).
Part of form1.cs file:
UserControl1 us = ctrl as UserControl1;
us.newThread = new Thread(new ThreadStart(us.wykres.CreateChart));
us.newThread.Start();
charts.cs file:
public class Charts
{
private StreamWriter sw = new StreamWriter("logFile.txt", true);
static readonly object LogLock = new object();
private ZedGraphControl zzz;
public ZedGraphControl ZZZ
{
get { return zzz; }
set { zzz = value; }
}
private UserControl1 uc1;
public UserControl1 Uc1
{
get { return uc1; }
set { uc1 = value; }
}
//jakiś kod
void WriteLog(string wpis, StreamWriter streamW)
{
lock (LogLock)
{
streamW.WriteLine(wpis);
streamW.Flush();
}
}
public void CreateChart()
{
try
{
//tutaj znów jakiś kod
//poniżej najważniejsza
while ()
{
if ()
{
if (go == false)
{
ZZZ.Invoke(Uc1.warnDelegate, "Osiągnięto strefę bezpiecznych wartości");
}
wpis = "jakis string";
WriteLog(wpis, sw);
wpis = null;
}
if ()
{
if ()
{
ZZZ.Invoke(Uc1.warnDelegate, "Osiągnięto strefę 1");
}
wpis = "jakis string";
WriteLog(wpis, sw);
wpis = null;
}
else if ()
{
if ()
{
ZZZ.Invoke(Uc1.warnDelegate, "Osiągnięto strefę 2");
}
wpis = "jakis string";
WriteLog(wpis, sw);
wpis = null;
}
//jakiś kod odnośnie rysowania wykresow
ZZZ.Invoke(Uc1.myDelegate);
Thread.Sleep(odstepCzasu * 1000);
}
}
catch (InvalidOperationException e)
{
MessageBox.Show(e.Message);
}
catch (ThreadAbortException)
{
}
}
}
}
Part of userControl1.cs file:
public delegate void RefreshDelegate();
public delegate void ShowWarningDialogDelegate(string aaa, string bbb, string ccc);
public RefreshDelegate myDelegate;
public ShowWarningDialogDelegate warnDelegate;
public Thread newThread = null;
public Charts wykres = null;
public UserControl1()
{
InitializeComponent();
wykres = new Charts();
wykres.ZZZ = zedGraphControl1;
wykres.Uc1 = this;
myDelegate = new RefreshDelegate(wykres.ZZZ.Refresh);
warnDelegate = new ShowWarningDialogDelegate(minDelegate);
}
private void minDelegate(string strLabel1, string strLabel2)
{
WarningForm forma = new WarningForm(strLabel1, strLabel2);
forma.Show();
}
Can you show me how to synchronize it to happen that a few threads have accessed in the same time to a log file (when they want to save something)? I heard that this is typical producer-consumer problem but I d'nt know how to use it in my case. I will be very greatefull for any halp. Regards.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用 C# 的 lock() 函数来锁定一个对象,这将允许您在 lock() 函数内一次只允许一个线程。
1) 创建一个对象用作类中的锁。
2) 将日志记录代码移至其自己的方法中,并使用 lock() 函数一次强制只有一个线程执行关键区域,在本例中为 StreamWriter 内容。
3) 使用任意数量的线程同时调用线程安全日志记录方法。
You can use the lock() function of C# to lock an object which will allow you to only allow one thread at a time inside the lock() function.
1) Create an object to use as a lock in your class.
2) Move your logging code into it's own method and use the lock() function to force only one thread at a time to execute the critical area, in this case the StreamWriter stuff.
3) Call your threadsafe logging method concurrently with as many threads as you want.
看一下
信号量
类。您可以使用它来同步访问文件的线程。简而言之,您希望在任何给定时间点只有一个线程写入文件。take a look at the
Semaphore
class. You can use it to synchronize threads accessing the file. In short, you want to have only one thread write to the file at any given point in time.您可以创建额外的方法来写入日志。
然后就可以同步这个方法了。
You can create additional method for writing log.
Then you can synchronize this method.