В form1 у меня есть этот общедоступный метод:
public void CombindedStringFix()
{
BeginUpdate();
label3.Text = SaveOldHtml.HtmlLoadedFileNumber.ToString();
richTextBox1.Clear();
List<string> newText1 = new List<string>();
label1.Select();
scrollerList = new List<string>(Filters.newTextWithoutLinks);
scrollerText = string.Join(Environment.NewLine, scrollerList);
scroller1.TextToScroll = scrollerText;
combindedString = string.Join(Environment.NewLine, SaveOldHtml.newText);
richTextBox1.Text = combindedString;
string[] rlines = richTextBox1.Lines;
timer3.Start();
richTextBox1.SelectionStart = 0;
richTextBox1.SelectionLength = rlines[0].Length;
richTextBox1.SelectionColor = Color.Red;
richTextBox1.Select(rlines[0].Length, rlines[1].Length + 1);
richTextBox1.SelectionColor = Color.Green;
EndUpdate();
}
И затем в новом классе я вызываю этот метод:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Timers;
using System.Windows.Forms;
namespace ScrollLabelTest
{
class SaveOldHtml
{
private static Form1 frm1 = null;
private static int count;
private static System.Timers.Timer _timer = new System.Timers.Timer();
private static string page;
public static List<string> newText = new List<string>();
public static int HtmlLoadedFileNumber = 0;
public SaveOldHtml(string DirectoryToSave,int count, string contents)
{
System.IO.File.WriteAllText(DirectoryToSave + "Page" + count.ToString("D6")
+ ".html", contents);
}
public SaveOldHtml(string DirectoryToSave, List<string> newTextList, int count)
{
using (StreamWriter myStream = new StreamWriter(DirectoryToSave + "newTextList" + count.ToString("D6")
+ ".txt"))
{
for (int i = 0; i < newTextList.Count; i++)
{
myStream.WriteLine(newTextList[i]);
}
}
}
public static void Start(Form1 form)
{
frm1 = form;
_timer.Elapsed += _timer_Elapsed;
_timer.Interval = 10000;
count = 5;
LoadOldHtmlFiles();
frm1.CombindedStringFix();
_timer.Start();
}
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
_timer.Stop();
LoadOldHtmlFiles();
frm1.CombindedStringFix();
_timer.Start();
}
private static void LoadOldHtmlFiles()
{
page = File.ReadAllText(@"c:\temp\OldHtml\page" + count.ToString("D6") + ".html");
ListsExtractions.OffExtractions(@"c:\temp\OldHtml\page" + count.ToString("D6") + ".html", page, newText);
count ++;
HtmlLoadedFileNumber++;
}
}
}
Как только я вызываю метод CombindedStringFix в методе Start в классе, который он работает, и выполняет все строки в CombindedStringFix. Я использовал breakpoiont, и он делает все.
Но в следующий раз, когда он вызывает метод в событии отметки таймера в новом классе, я использовал точку останова и после того, как он выполнил первую строку BegingUpdate(); он просто ограничивается и никогда не останавливается в событии таймера и никогда не будет продолжать работу над BeginUpdate();
Даже если я удалю BeginUpdate(); поэтому он будет делать первую строку, а затем продолжить, она никогда не переместится на следующую строку/с.
Я видел теперь, что я получаю исключение в событии таймера:
Неверная операция поперечного потока: элемент управления Form1 доступен из потока, отличного от потока, который был создан на
System.InvalidOperationException was caught
HResult=-2146233079
Message=Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on.
Source=System.Windows.Forms
StackTrace:
at System.Windows.Forms.Control.get_Handle()
at ScrollLabelTest.Form1.BeginUpdate() in e:\scrolllabel\ScrollLabel\ScrollLabel\Form1.cs:line 69
at ScrollLabelTest.Form1.CombindedStringFix() in e:\scrolllabel\ScrollLabel\ScrollLabel\Form1.cs:line 280
at ScrollLabelTest.SaveOldHtml._timer_Elapsed(Object sender, ElapsedEventArgs e) in e:\scrolllabel\ScrollLabel\ScrollLabel\SaveOldHtml.cs:line 64
InnerException:
Я думаю, что-то с переменной frm1.
Вероятно, проблема заключается в том, что существует исключение, которое происходит где-то в вашем истекшем событии, и таймер никогда не запускается снова. Вы можете установить точку останова и следовать ей, чтобы в первый раз войти, чтобы увидеть, где/если она терпит неудачу. Кроме того, вы можете запрограммировать его, чтобы начать резервное копирование независимо:
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
_timer.Stop();
try
{
LoadOldHtmlFiles();
frm1.CombindedStringFix();
}
catch (Exception ex)
{
// do something (or nothing) with the exception
}
finally
{
_timer.Start();
}
}
Поскольку вы подтвердили, что происходит перекрестное потоковое исключение, я бы рекомендовал прочитать:
Как сделать безопасные вызовы для Windows Forms Controls
Вот их демо в случае, если ссылка когда-либо сломана:
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace CrossThreadDemo
{
public class Form1 : Form
{
// This delegate enables asynchronous calls for setting
// the text property on a TextBox control.
delegate void SetTextCallback(string text);
// This thread is used to demonstrate both thread-safe and
// unsafe ways to call a Windows Forms control.
private Thread demoThread = null;
// This BackgroundWorker is used to demonstrate the
// preferred way of performing asynchronous operations.
private BackgroundWorker backgroundWorker1;
private TextBox textBox1;
private Button setTextUnsafeBtn;
private Button setTextSafeBtn;
private Button setTextBackgroundWorkerBtn;
private System.ComponentModel.IContainer components = null;
public Form1()
{
InitializeComponent();
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
// This event handler creates a thread that calls a
// Windows Forms control in an unsafe way.
private void setTextUnsafeBtn_Click(
object sender,
EventArgs e)
{
this.demoThread =
new Thread(new ThreadStart(this.ThreadProcUnsafe));
this.demoThread.Start();
}
// This method is executed on the worker thread and makes
// an unsafe call on the TextBox control.
private void ThreadProcUnsafe()
{
this.textBox1.Text = "This text was set unsafely.";
}
// This event handler creates a thread that calls a
// Windows Forms control in a thread-safe way.
private void setTextSafeBtn_Click(
object sender,
EventArgs e)
{
this.demoThread =
new Thread(new ThreadStart(this.ThreadProcSafe));
this.demoThread.Start();
}
// This method is executed on the worker thread and makes
// a thread-safe call on the TextBox control.
private void ThreadProcSafe()
{
this.SetText("This text was set safely.");
}
// This method demonstrates a pattern for making thread-safe
// calls on a Windows Forms control.
//
// If the calling thread is different from the thread that
// created the TextBox control, this method creates a
// SetTextCallback and calls itself asynchronously using the
// Invoke method.
//
// If the calling thread is the same as the thread that created
// the TextBox control, the Text property is set directly.
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}
// This event handler starts the form
// BackgroundWorker by calling RunWorkerAsync.
//
// The Text property of the TextBox control is set
// when the BackgroundWorker raises the RunWorkerCompleted
// event.
private void setTextBackgroundWorkerBtn_Click(
object sender,
EventArgs e)
{
this.backgroundWorker1.RunWorkerAsync();
}
// This event handler sets the Text property of the TextBox
// control. It is called on the thread that created the
// TextBox control, so the call is thread-safe.
//
// BackgroundWorker is the preferred way to perform asynchronous
// operations.
private void backgroundWorker1_RunWorkerCompleted(
object sender,
RunWorkerCompletedEventArgs e)
{
this.textBox1.Text =
"This text was set safely by BackgroundWorker.";
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.setTextUnsafeBtn = new System.Windows.Forms.Button();
this.setTextSafeBtn = new System.Windows.Forms.Button();
this.setTextBackgroundWorkerBtn = new System.Windows.Forms.Button();
this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(12, 12);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(240, 20);
this.textBox1.TabIndex = 0;
//
// setTextUnsafeBtn
//
this.setTextUnsafeBtn.Location = new System.Drawing.Point(15, 55);
this.setTextUnsafeBtn.Name = "setTextUnsafeBtn";
this.setTextUnsafeBtn.TabIndex = 1;
this.setTextUnsafeBtn.Text = "Unsafe Call";
this.setTextUnsafeBtn.Click += new System.EventHandler(this.setTextUnsafeBtn_Click);
//
// setTextSafeBtn
//
this.setTextSafeBtn.Location = new System.Drawing.Point(96, 55);
this.setTextSafeBtn.Name = "setTextSafeBtn";
this.setTextSafeBtn.TabIndex = 2;
this.setTextSafeBtn.Text = "Safe Call";
this.setTextSafeBtn.Click += new System.EventHandler(this.setTextSafeBtn_Click);
//
// setTextBackgroundWorkerBtn
//
this.setTextBackgroundWorkerBtn.Location = new System.Drawing.Point(177, 55);
this.setTextBackgroundWorkerBtn.Name = "setTextBackgroundWorkerBtn";
this.setTextBackgroundWorkerBtn.TabIndex = 3;
this.setTextBackgroundWorkerBtn.Text = "Safe BW Call";
this.setTextBackgroundWorkerBtn.Click += new System.EventHandler(this.setTextBackgroundWorkerBtn_Click);
//
// backgroundWorker1
//
this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
//
// Form1
//
this.ClientSize = new System.Drawing.Size(268, 96);
this.Controls.Add(this.setTextBackgroundWorkerBtn);
this.Controls.Add(this.setTextSafeBtn);
this.Controls.Add(this.setTextUnsafeBtn);
this.Controls.Add(this.textBox1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
}
}
Я попытаюсь ответить на это, но без полного контекста это немного грубо.
CombindedStringFix()
вас есть то, что похоже на объект таймера, называемый timer3
. Имя этого таймера не похоже на имя вашего таймера в классе SaveOldHtml
, и я не вижу свойство/поле, открытое этим именем. Мне интересно, есть ли у вас два таймера, которые могут быть смущены.Я знаю, что это плохая форма, чтобы не отвечать на вопрос, но в отсутствие более специфических/более источников это лучшее, что я могу собрать. Любой контекст, и я могу предложить больше помощи!