如何修复C#中后台工作者日志不匹配的问题 [英] How can I fix to mismatching the logs in backgroundworkers in C#

查看:68
本文介绍了如何修复C#中后台工作者日志不匹配的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨朋友们,



刚刚编辑了代码并制作了一个小程序,分享如下:



一旦运行代码,后台工作人员都正常工作,但在日志文件中,缺少一些日志。





 使用系统; 
使用 System.Collections.Generic;
使用 System.ComponentModel;
使用 System.Data;
使用 System.Drawing;
使用 System.Linq;
使用 System.Text;
使用 System.Windows.Forms;
使用 System.IO;


使用 System.Globalization;


命名空间 BGTESTING
{
public partial class Form1:Form
{
private BackgroundWorker myWorker1 = new BackgroundWorker();
private BackgroundWorker myWorker2 = new BackgroundWorker();
private delegate void UpdateStatusDelegate ();
private UpdateStatusDelegate updateStatusDelegate = null ;
public static string mystatus ;
static int serverStatus = 0 ;
public static string AppLogFile = SG_LeadServer;
public static string logPath = Directory.GetCurrentDirectory()+ \\LOGS \\ + DateTime.Now .ToString( dd / MM / yyyy,CultureInfo.InvariantCulture).Replace( / );
string strappPath = Directory.GetCurrentDirectory();
public Form1()
{
InitializeComponent();
myWorker1.DoWork + = new DoWorkEventHandler(myWorker1_DoWork);
myWorker1.RunWorkerCompleted + = new RunWorkerCompletedEventHandler(myWorker1_RunWorkerCompleted);
myWorker1.ProgressChanged + = new ProgressChangedEventHandler(myWorker1_ProgressChanged);
myWorker1.WorkerReportsProgress = true ;
myWorker1.WorkerSupportsCancellation = true ;

myWorker2.DoWork + = new DoWorkEventHandler(myWorker2_DoWork);
myWorker2.RunWorkerCompleted + = new RunWorkerCompletedEventHandler(myWorker2_RunWorkerCompleted);
myWorker2.ProgressChanged + = new ProgressChangedEventHandler(myWorker2_ProgressChanged);
myWorker2.WorkerReportsProgress = true ;
myWorker2.WorkerSupportsCancellation = true ;
}
protected void myWorker1_DoWork( object sender,DoWorkEventArgs e)
{
BackgroundWorker sendingWorker =(BackgroundWorker)sender;
object [] arrObjects =( object [])e .Argument;
int maxValue =( int )arrObjects [ 0 ];
for int i = 1 ; i < = 20000000 ; i ++)
{
if (!sendingWorker.CancellationPending)
{
myWriteBC1(i);
}
其他
{
e.Cancel = true ;
this .Invoke( this .updateStatusDelegate);
break ;
}
// i = 1;
}
}
受保护 void myWorker1_RunWorkerCompleted( object sender,RunWorkerCompletedEventArgs e)
{
if (!e.Cancelled&& e.Error == null // 检查工作人员是否已被取消或是否有错误已发生
{
string result =( string )e。结果; // 从后台线程获取结果
mystatus = result;
this .Invoke( this .updateStatusDelegate);
}
其他 如果(e.Cancelled)
{
mystatus = 用户取消了工人1;
}
else
{
mystatus = 发生错误;
this .Invoke( this .updateStatusDelegate);
}
Startbutton.Enabled = true ; // 重新启动开始按钮
}
受保护 void myWorker1_ProgressChanged( object sender,ProgressChangedEventArgs e)
{
mystatus = 进入流程更改循环.... pradip..please查看此;
}

protected void myWorker2_DoWork( object sender,DoWorkEventArgs e)
{
BackgroundWorker sendingWorker =(BackgroundWorker)sender;
object [] arrObjects =( object [])e .Argument;
int maxValue =( int )arrObjects [ 0 ];
for int i = 3000000 ; i < = 20000000 ; i ++)
{
if (!sendingWorker.CancellationPending)
{
myWriteBC2(i);
}
其他
{
e.Cancel = true ;
this .Invoke( this .updateStatusDelegate);
break ;
}
}
}
受保护 void myWorker2_RunWorkerCompleted ( object sender,RunWorkerCompletedEventArgs e)
{
if (!e.Cancelled && e.Error == null
{
string 结果=( string )e .Result;
mystatus =结果;
this .Invoke( this .updateStatusDelegate);
}
其他 如果(e.Cancelled)
{
mystatus = 用户取消了工人2;
}
else
{
mystatus = 发生错误;
this .Invoke( this .updateStatusDelegate);
}
Startbutton.Enabled = true ;
}
受保护 void myWorker2_ProgressChanged( object sender,ProgressChangedEventArgs e)
{
mystatus = 进入流程改变循环.... pradip..please看看这个;
}

private void Form1_Load( object sender,EventArgs e)
{
this .updateStatusDelegate = new UpdateStatusDelegate( this .UpdateStatus);
if (serverStatus == 0
{
ServerStatustextBox。 Text = 已停止;
Startbutton.Text = Start;
}
else
{
Startbutton.Text = 停止;
ServerStatustextBox.Text = 正在运行;
}
mystatus = 当前状态: + ServerStatustextBox.Text + 这是在表单上加载;

this .Invoke( this .updateStatusDelegate);
}

private void Startbutton_Click( object sender,EventArgs e)
{
if (serverStatus == 0
{
AppLogFile = SG_LeadServer;
serverStatus = 1 ;
Startbutton.Text = 停止;
ServerStatustextBox.Text = 正在运行;
if (!myWorker1.IsBusy)
{
Int32 i = 1 ;
int numericValue = i;
object [] arrObjects = new object [] {numericValue};
myWorker1.RunWorkerAsync(arrObjects);
}
if (!myWorker2.IsBusy)
{
Int32 i = 1 ;
int numericValue = i;
object [] arrObjects = new object [] {numericValue};
myWorker2.RunWorkerAsync(arrObjects);
}
}
else if (serverStatus == 1
{
serverStatus = 0 ;
Startbutton.Text = Start;
ServerStatustextBox.Text = 已停止;
AppLogFile = SG_LeadServer;
myWorker1.CancelAsync();
myWorker2.CancelAsync();
mystatus = 为servID 8aa收到停止操作 + DateTime.Now.ToString() ;
}
mystatus = 当前状态: + ServerStatustextBox.Text;
this .Invoke( this .updateStatusDelegate);
}
public void UpdateStatus()
{
if (listBox1.Items.Count > 500 )listBox1.Items.Clear();
if (mystatus!=
{
this .listBox1.Items.Insert( 0 ,DateTime.Now.ToString( dd-MM-yyyy HH:mm:ss)+ < span class =code-string>
==> + mystatus);
writeLogFile(logPath,AppLogFile,mystatus);
}
mystatus = ;
}
public void writeLogFile( string strLogPath, String strFileName, string strLogtxt)
{
if (!Directory.Exists(strLogPath))
{
Directory.CreateDirectory(strLogPath);
}
string strfullPath = strLogPath + \\ + strFileName + .txt;
StreamWriter日志;
if (!File.Exists(strfullPath))
{
log = new StreamWriter(strfullPath);
}
else
{
log = File.AppendText(strfullPath);
}
log.WriteLine(DateTime.Now.ToString( dd-MM-yyyy HH :mm:ss)+ ==> + strLogtxt);
log.Close();
}
void myWriteBC1( int k)
{
AppLogFile = LOG_BC1;
mystatus = 这是在BC1_DoWork + k.ToString();
this .Invoke( this .updateStatusDelegate);
System.Threading.Thread.Sleep( 500 );
}
void myWriteBC2( int k)
{
AppLogFile = LOG_BC2;
mystatus = 这是在BC2_DoWork + k.ToString();
this .Invoke( this .updateStatusDelegate);
System.Threading.Thread.Sleep( 500 );
}

}
}





我尝试过:



我需要明智地生成日志文件backgroundworker,它不应该不匹配。

解决方案

< blockquote>该代码没有多大意义......并且它不可维护。



对代码的一些评论。可以找到更多的问题:



1)如果你使用后台工作者,你可能不需要显式的调用。请改用 ReportProgress



2)如果您的数据中有超过5行,则某些行可能不会如果所有工人都很忙,你可以处理。



3)在你的工人中,你设置每次迭代到 1 。这将创建一个无限循环但是以非常暗的方式。如果你想要一个无限循环,那就不要使用变量 i



4)它不会报告 i (注释掉代码),如果除了第一个之外的值总是2,那就很有意义。



5)收到的拼写错误。



6)重复代码太多了。你读过DRY吗?

不要重复自己 - 维基百科,免费的百科全书 [ ^ ]

不要重复自己 - 程序员97事情 [ ^ ]

不要重复自己 [ ^ ]



7)你的功能太复杂了。您应阅读有关SRP的文章。

单一责任原则 - 维基百科,免费的百科全书 [< a href =https://en.wikipedia.org/wiki/Single_responsibility_principletarget =_ blanktitle =New Window> ^ ]

SOLID:第1部分 - 单一责任原则 [ ^ ]

单一责任原则|面向对象设计 [ ^ ]

固体原则:单一责任原则 - >什么,为什么以及如何。 [ ^ ]



8)避免代码中的硬编码常量。你的代码中有很多:

500 (列表中的最大项目数)
1 (某些服务器状态)

SG_LeadServer (硬编码字符串)

至少,将常量放在类级别,这样你就可以找到单一且容易找到它们的地方如果你改变主意就要更新一个值。



9)避免像这样的无用评论: //发出取消请求以阻止后台工作者。评论不应重复(明显的)代码(除了学校教学目的)。



10)如果你有5个主题,那么没有意义所有这些都更新了相同的状态。您可能应该在您的案例中显示累积状态。



11)后台工作人员的延迟通常是可疑的。你为什么要放慢处理速度呢。



12)你应该删除过时的代码或把它放在 #if obsolete_code / #endif 或至少添加关于代码被注释掉的原因的评论。在一个论坛这样的未使用的代码并没有真正的帮助,虽然它给了我们一些关于你尝试的提示,但我们仍然不知道为什么它被注释掉了。



13 )我没有看到锁的目的(使用它的代码被注释掉)。当您从 DoWork 处理程序调用调用时,您已经知道单个线程将在该处执行该代码同一时间(假设没有其他线程直接调用代码---在这种情况下,由于对UI的跨线程调用,代码无论如何都会失败)。



14 )甚至最糟糕的是代码是与5名工人一起工作的硬编码。如果想要尝试更多或更少的工作人员来看到对性能的影响,很难调整代码。



15)你应该避免混合非UI代码和同一类中的UI代码。在这种情况下更是如此,每个工作人员的代码或多或少都是其他工作人员代码的副本。在这种情况下,您应该至少有2个类... UI中的代码应该是极简主义的。如果您想在其他平台(iOS,ASP.NET,Android,UWP,WPF,...)上移植代码,您希望尽可能多地共享代码。


使用锁定声明。

锁定声明(C#参考) [ ^ ]


Hi Friends,

Just edited the code and made it a small program, sharing the below:

Once run the code, both the background workers work properly but in log file , some logs are missing.


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.Globalization;


namespace BGTESTING
{
    public partial class Form1 : Form
    {
        private BackgroundWorker myWorker1 = new BackgroundWorker();
        private BackgroundWorker myWorker2 = new BackgroundWorker();
        private delegate void UpdateStatusDelegate();
        private UpdateStatusDelegate updateStatusDelegate = null;
        public static string mystatus;
        static int serverStatus = 0;
        public static string AppLogFile = "SG_LeadServer";
        public static string logPath = Directory.GetCurrentDirectory() + "\\LOGS\\" + DateTime.Now.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture).Replace("/", "");
        string strappPath = Directory.GetCurrentDirectory();
        public Form1()
        {
            InitializeComponent();
            myWorker1.DoWork += new DoWorkEventHandler(myWorker1_DoWork);
            myWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(myWorker1_RunWorkerCompleted);
            myWorker1.ProgressChanged += new ProgressChangedEventHandler(myWorker1_ProgressChanged);
            myWorker1.WorkerReportsProgress = true;
            myWorker1.WorkerSupportsCancellation = true;

            myWorker2.DoWork += new DoWorkEventHandler(myWorker2_DoWork);
            myWorker2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(myWorker2_RunWorkerCompleted);
            myWorker2.ProgressChanged += new ProgressChangedEventHandler(myWorker2_ProgressChanged);
            myWorker2.WorkerReportsProgress = true;
            myWorker2.WorkerSupportsCancellation = true;
        }
        protected void myWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker sendingWorker = (BackgroundWorker)sender;
            object[] arrObjects = (object[])e.Argument;
            int maxValue = (int)arrObjects[0];
            for (int i = 1; i <= 20000000; i++)
            {
                if (!sendingWorker.CancellationPending)
                {
                    myWriteBC1(i);
                }
                else
                {
                    e.Cancel = true;
                    this.Invoke(this.updateStatusDelegate);
                    break;
                }
                //i = 1;
            }
        }
        protected void myWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!e.Cancelled && e.Error == null)//Check if the worker has been cancelled or if an error occured
            {
                string result = (string)e.Result;//Get the result from the background thread
                mystatus = result;
                this.Invoke(this.updateStatusDelegate);
            }
            else if (e.Cancelled)
            {
                mystatus = "User Cancelled IN WORKER 1";
            }
            else
            {
                mystatus = "An error has occured";
                this.Invoke(this.updateStatusDelegate);
            }
            Startbutton.Enabled = true;//Reneable the start button
        }
        protected void myWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            mystatus = "go in Process changes loop....pradip..please look into this";
        }

        protected void myWorker2_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker sendingWorker = (BackgroundWorker)sender;
            object[] arrObjects = (object[])e.Argument;
            int maxValue = (int)arrObjects[0];
            for (int i = 3000000; i <= 20000000; i++)
            {
                if (!sendingWorker.CancellationPending)
                {
                    myWriteBC2(i);
                }
                else
                {
                    e.Cancel = true;
                    this.Invoke(this.updateStatusDelegate);
                    break;
                }
            }
        }
        protected void myWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!e.Cancelled && e.Error == null)
            {
                string result = (string)e.Result;
                mystatus = result;
                this.Invoke(this.updateStatusDelegate);
            }
            else if (e.Cancelled)
            {
                mystatus = "User Cancelled IN WORKER 2";
            }
            else
            {
                mystatus = "An error has occured";
                this.Invoke(this.updateStatusDelegate);
            }
            Startbutton.Enabled = true;
        }
        protected void myWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            mystatus = "go in Process changes loop....pradip..please look into this";
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.updateStatusDelegate = new UpdateStatusDelegate(this.UpdateStatus);
            if (serverStatus == 0)
            {
                ServerStatustextBox.Text = "Stopped";
                Startbutton.Text = "Start";
            }
            else
            {
                Startbutton.Text = "Stop";
                ServerStatustextBox.Text = "Running";
            }
            mystatus = "Current Status: " + ServerStatustextBox.Text+" this is on form Load";

            this.Invoke(this.updateStatusDelegate);
        }

        private void Startbutton_Click(object sender, EventArgs e)
        {
            if (serverStatus == 0)
            {
                AppLogFile = "SG_LeadServer";
                serverStatus = 1;
                Startbutton.Text = "Stop";
                ServerStatustextBox.Text = "Running";
                if (!myWorker1.IsBusy)
                {
                    Int32 i = 1;
                    int numericValue = i;
                    object[] arrObjects = new object[] { numericValue };
                    myWorker1.RunWorkerAsync(arrObjects);
                }
                if (!myWorker2.IsBusy)
                {
                    Int32 i = 1;
                    int numericValue = i;
                    object[] arrObjects = new object[] { numericValue };
                    myWorker2.RunWorkerAsync(arrObjects);
                }
            }
            else if (serverStatus == 1)
            {
                    serverStatus = 0;
                    Startbutton.Text = "Start";
                    ServerStatustextBox.Text = "Stopped";
                    AppLogFile = "SG_LeadServer";
                    myWorker1.CancelAsync();
                    myWorker2.CancelAsync();
                    mystatus = "Stop Action Received for servID 8aa " + DateTime.Now.ToString();
            }
            mystatus = "Current Status: " + ServerStatustextBox.Text;
            this.Invoke(this.updateStatusDelegate);
        }
        public void UpdateStatus()
        {
            if (listBox1.Items.Count > 500) listBox1.Items.Clear();
            if (mystatus != "")
            {
                this.listBox1.Items.Insert(0, DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss") + " ==> " + mystatus);
                writeLogFile(logPath, AppLogFile, mystatus);
            }
            mystatus = "";
        }
        public void writeLogFile(string strLogPath, String strFileName, string strLogtxt)
        {
            if (!Directory.Exists(strLogPath))
            {
                Directory.CreateDirectory(strLogPath);
            }
            string strfullPath = strLogPath + "\\" + strFileName + ".txt";
            StreamWriter log;
            if (!File.Exists(strfullPath))
            {
                log = new StreamWriter(strfullPath);
            }
            else
            {
                log = File.AppendText(strfullPath);
            }
            log.WriteLine(DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss") + " ==> " + strLogtxt);
            log.Close();
        }
        void myWriteBC1(int k)
        {
            AppLogFile = "LOG_BC1";
            mystatus = "This is in BC1_DoWork    " + k.ToString();
            this.Invoke(this.updateStatusDelegate);
            System.Threading.Thread.Sleep(500);
        }
        void myWriteBC2(int k)
        {
            AppLogFile = "LOG_BC2";
            mystatus = "This is in BC2_DoWork    " + k.ToString();
            this.Invoke(this.updateStatusDelegate);
            System.Threading.Thread.Sleep(500);
        }
       
    }
}



What I have tried:

I need to generate the log file backgroundworker wise and it should not mismatch.

解决方案

That code does not make much sense... and it is not maintainable.

Some comments on the code. Lot more issues can be found:

1)If you use background workers, you probably don't need explicit Invoke. Use ReportProgress instead.

2) If you have more than 5 rows in your data, some row might not be processed as you do nothing if all worker are busy.

3) In your workers, you set i to 1 in each iteration. This will create an "infinite" loop but in a very obscur way. If you want an infinite loop, then don't use variable i.

4) It does not make much sense to report on i (commented out code), if the value is always 2 except the first one.

5) Spelling error in recived.

6) Way too much duplicate code. Have you ever read on DRY?
Don't repeat yourself - Wikipedia, the free encyclopedia[^]
Don't Repeat Yourself - Programmer 97-things[^]
Dont Repeat Yourself[^]

7)Your functions are too complicate. You should read articles on SRP.
Single responsibility principle - Wikipedia, the free encyclopedia[^]
SOLID: Part 1 - The Single Responsibility Principle[^]
Single Responsibility Principle | Object Oriented Design[^]
SOLID Principles: Single Responsibility Principle -> What, Why and How.[^]

8) Avoid hard-coded constants in code. You have a bunch of them in your code:
500 (maximum number of items in list)
1 (some server status)
"SG_LeadServer" (hard-coded string)
At the very minimum, put constants at class level so you have single and easy to find place to find them and only one value to update if you change your mind.

9) Avoid useless comments like this one: //Issue a cancellation request to stop the background worker. Comment should not repeat the (obvious) code (except for teaching purpose in school book).

10) If you have 5 threads, then it does not make sense that all of them update the same status. You should probably display a cumulative status in your case.

11) Delay in background worker is often suspicious. Why would you want to slow down processing.

12) You should remove obsolete code or put it inside #if obsolete_code / #endif or at least add a comment about why the code was commented out. In a forum such unused code is not really helpful although it give us some hint about what you try but we still don't know why it was commented out.

13) I don't see the purpose of the lock (code that use it is commented out). As you are calling Invoke from the DoWork handler, you already know that a single thread will be executing that code at the same time (assuming no other thread directly call the code --- in which case, the code would fails anyway because of cross-thread calls to UI).

14) Even worst is the fact that the code is hard-code to work with 5 workers. If one want to try with more or less workers to see the effect on performance, it is hard to adapt the code.

15) You should avoid mixing non UI code and UI code in the same class. This is even more the case here where code for each worker is more or less a copy of the code of other workers. In such case, you should have at least 2 classes... Code in the UI should be minimalist. If you ever want to port code on other platform (iOS, ASP.NET, Android, UWP, WPF,...) you want to share as much as possible code.


Use "lock" statement.
lock Statement (C# Reference)[^]


这篇关于如何修复C#中后台工作者日志不匹配的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆