Вам нужен сдержанный жадный токен :
abc(?:(?!abc|xyz|123).)*123(?:(?!abc|xyz).)*xyz
См. демонстрацию regex
Чтобы убедиться, что она соответствует через строки, используйте флаг re.DOTALL
при компиляции регулярного выражения.
Обратите внимание, что для достижения более высокой производительности с таким тяжелым шаблоном вам следует рассмотреть возможность его развертывания.
Сведения о шаблоне:
abc
- соответствие abc
(?:(?!abc|xyz|123).)*
- сопоставить любой символ, который не является отправной точкой для последовательностей символов abc
, xyz
или 123
123
- буквальная строка 123
(?:(?!abc|xyz).)*
- любой символ, который не является исходной точкой для последовательностей символов abc
или xyz
xyz
- конечная подстрока xyz
См. Диаграмму ниже (если используется re.S
, .
будет означать AnyChar
):
См. Демонстрацию Python :
import re
p = re.compile(r'abc(?:(?!abc|xyz|123).)*123(?:(?!abc|xyz).)*xyz', re.DOTALL)
s = "abc 123 xyz\nabc abc 123 xyz\nabc text 123 xyz\nabc text xyz xyz"
print(p.findall(s))
// => ['abc 123 xyz', 'abc 123 xyz', 'abc text 123 xyz']
Пожалуйста, прочитайте Threading Model в приложениях пользовательского интерфейса, чтобы понять основные понятия. Ссылка перемещается на страницу, описывающую модель потоков WPF. Тем не менее, Windows Forms использует ту же идею.
[/g22]
[/g23]
[/g24]
[/g25]
[/g26]
Прочитать ответы на вопрос Как обновить графический интерфейс из другого потока в C #? . Для C # 5.0 и .NET 4.5 рекомендуемым решением является здесь .
Это не рекомендуемый способ решить эту ошибку, но вы можете быстро ее подавить, она выполнит эту работу. Я предпочитаю это для прототипов или демонстраций. добавьте
CheckForIllegalCrossThreadCalls = false
в конструкторе Form1()
.
Действие y; // объявлен внутри класса
label1.Invoke (y = () => label1.Text = "text");
Вот альтернативный способ, если объект, с которым вы работаете, не имеет
(InvokeRequired)
Это полезно, если вы работаете с основной формой в классе, отличном от основной формы, с объект, который находится в основной форме, но не имеет InvokeRequired
delegate void updateMainFormObject(FormObjectType objectWithoutInvoke, string text);
private void updateFormObjectType(FormObjectType objectWithoutInvoke, string text)
{
MainForm.Invoke(new updateMainFormObject(UpdateObject), objectWithoutInvoke, text);
}
public void UpdateObject(ToolStripStatusLabel objectWithoutInvoke, string text)
{
objectWithoutInvoke.Text = text;
}
Он работает так же, как и выше, но это другой подход, если у вас нет объекта с invokerequired, но do имеют доступ к MainForm
Я знаю его слишком поздно. Однако даже сегодня, если у вас возникли проблемы с доступом к элементам управления перекрестными потоками? Это самый короткий ответ до даты: P
Invoke(new Action(() =>
{
label1.Text = "WooHoo!!!";
}));
Вот как я обращаюсь к любому управлению формой из потока.
Invoke or BeginInvoke cannot be called on a control until the window handle has been created
. Я решил здесь
– rupweb
24 January 2018 в 17:22
В тех же строках, что и в предыдущих ответах, но очень короткое дополнение, которое позволяет использовать все свойства Control без исключения перекрестного потока invoke.
Метод помощника
/// <summary>
/// Helper method to determin if invoke required, if so will rerun method on correct thread.
/// if not do nothing.
/// </summary>
/// <param name="c">Control that might require invoking</param>
/// <param name="a">action to preform on control thread if so.</param>
/// <returns>true if invoke required</returns>
public bool ControlInvokeRequired(Control c, Action a)
{
if (c.InvokeRequired) c.Invoke(new MethodInvoker(delegate
{
a();
}));
else return false;
return true;
}
Образец Использование
// usage on textbox
public void UpdateTextBox1(String text)
{
//Check if invoke requied if so return - as i will be recalled in correct thread
if (ControlInvokeRequired(textBox1, () => UpdateTextBox1(text))) return;
textBox1.Text = ellapsed;
}
//Or any control
public void UpdateControl(Color c, String s)
{
//Check if invoke requied if so return - as i will be recalled in correct thread
if (ControlInvokeRequired(myControl, () => UpdateControl(c, s))) return;
myControl.Text = s;
myControl.BackColor = c;
}
У меня была эта проблема с FileSystemWatcher
и выяснилось, что следующий код решил проблему:
fsw.SynchronizingObject = this
Затем элемент управления использует текущий объект формы для решения с событиями, и поэтому будет в одной и той же теме.
.SynchronizingObject = Me
– codingcoding
23 June 2016 в 02:40
this.Invoke(new MethodInvoker(delegate
{
//your code here;
}));
Самое чистое (и правильное) решение для кросс-потоковых проблем UI - использовать SynchronizationContext, см. Синхронизация вызовов с пользовательским интерфейсом в статье с несколькими потоками , это очень хорошо объясняет.
Новый взгляд с использованием Async / Await и callback. Вам нужна только одна строка кода, если вы сохраните метод расширения в своем проекте.
/// <summary>
/// A new way to use Tasks for Asynchronous calls
/// </summary>
public class Example
{
/// <summary>
/// No more delegates, background workers etc. just one line of code as shown below
/// Note it is dependent on the XTask class shown next.
/// </summary>
public async void ExampleMethod()
{
//Still on GUI/Original Thread here
//Do your updates before the next line of code
await XTask.RunAsync(() =>
{
//Running an asynchronous task here
//Cannot update GUI Thread here, but can do lots of work
});
//Can update GUI/Original thread on this line
}
}
/// <summary>
/// A class containing extension methods for the Task class
/// Put this file in folder named Extensions
/// Use prefix of X for the class it Extends
/// </summary>
public static class XTask
{
/// <summary>
/// RunAsync is an extension method that encapsulates the Task.Run using a callback
/// </summary>
/// <param name="Code">The caller is called back on the new Task (on a different thread)</param>
/// <returns></returns>
public async static Task RunAsync(Action Code)
{
await Task.Run(() =>
{
Code();
});
return;
}
}
Вы можете добавить другие вещи к методу расширения, например, обернуть его в оператор Try / Catch, чтобы вызывающий мог сказать ему, какой тип будет возвращен после завершения, обратный вызов исключения для вызывающего:
Добавление Try Catch, Auto Exception Logging и CallBack
/// <summary>
/// Run Async
/// </summary>
/// <typeparam name="T">The type to return</typeparam>
/// <param name="Code">The callback to the code</param>
/// <param name="Error">The handled and logged exception if one occurs</param>
/// <returns>The type expected as a competed task</returns>
public async static Task<T> RunAsync<T>(Func<string,T> Code, Action<Exception> Error)
{
var done = await Task<T>.Run(() =>
{
T result = default(T);
try
{
result = Code("Code Here");
}
catch (Exception ex)
{
Console.WriteLine("Unhandled Exception: " + ex.Message);
Console.WriteLine(ex.StackTrace);
Error(ex);
}
return result;
});
return done;
}
public async void HowToUse()
{
//We now inject the type we want the async routine to return!
var result = await RunAsync<bool>((code) => {
//write code here, all exceptions are logged via the wrapped try catch.
//return what is needed
return someBoolValue;
},
error => {
//exceptions are already handled but are sent back here for further processing
});
if (result)
{
//we can now process the result because the code above awaited for the completion before
//moving to this statement
}
}
Вы хотите использовать Invoke или BeginInvoke для минимальной части работы, необходимой для изменения пользовательского интерфейса. Ваш «тяжелый» метод должен выполняться в другом потоке (например, через BackgroundWorker), но затем с помощью Control.Invoke / Control.BeginInvoke только для обновления пользовательского интерфейса. Таким образом, ваш поток пользовательского интерфейса будет свободно обрабатывать события пользовательского интерфейса и т. Д.
См. Мою статью для потоковой передачи для примера WinForms - хотя статья была написана ранее BackgroundWorker прибыл на место происшествия, и, боюсь, я не обновил его в этом отношении. BackgroundWorker немного упрощает обратный вызов.
Существует два варианта операций с поперечными потоками.
Control.InvokeRequired Property
, а второй - использовать
SynchronizationContext Post Method
Control.InvokeRequired полезен только при работе с элементами управления, унаследованными от Control класс, в то время как SynchronizationContext можно использовать в любом месте. Некоторая полезная информация относится к следующим ссылкам:
Пользовательский интерфейс Cross Thread Update | .Net
Пользовательский интерфейс Cross Thread Update с использованием SynchronizationContext | .Net
Тот же вопрос: How-to-update-the-gui-from-another-thread-in-c
Two Ways:
Пример:
public class data_holder_for_controls
{
//it will hold value for your label
public string status = string.Empty;
}
class Demo
{
public static data_holder_for_controls d1 = new data_holder_for_controls();
static void Main(string[] args)
{
ThreadStart ts = new ThreadStart(perform_logic);
Thread t1 = new Thread(ts);
t1.Start();
t1.Join();
//your_label.Text=d1.status; --- can access it from any thread
}
public static void perform_logic()
{
//put some code here in this function
for (int i = 0; i < 10; i++)
{
//statements here
}
//set result in status variable
d1.status = "Task done";
}
}
Вам нужно посмотреть пример Backgroundworker: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx Особенно, как он взаимодействует с уровнем пользовательского интерфейса , Основываясь на вашей публикации, это, похоже, отвечает на ваши вопросы.
Элементы управления в .NET не являются в общем потокобезопасными. Это означает, что вам не следует обращаться к элементу управления из потока, отличного от того, в котором он живет. Чтобы обойти это, вам нужно вызвать элемент управления, который пытается выполнить ваш второй образец.
Однако в вашем случае все, что вы сделали, - это передать длинный метод обратно в основной поток. Конечно, это не то, что вы хотите сделать. Вам нужно переосмыслить это немного, чтобы все, что вы делали в основном потоке, устанавливало быстрое свойство здесь и там.
Я нахожу код check-and-invoke, который должен быть усеян во всех методах, связанных с формами, слишком многословным и ненужным. Вот простой метод расширения, который позволяет полностью устранить его:
public static class Extensions
{
public static void Invoke<TControlType>(this TControlType control, Action<TControlType> del)
where TControlType : Control
{
if (control.InvokeRequired)
control.Invoke(new Action(() => del(control)));
else
del(control);
}
}
И тогда вы можете просто сделать это:
textbox1.Invoke(t => t.Text = "A");
Больше не возиться - просто.
Например, чтобы получить текст из элемента управления потоком пользовательского интерфейса:
Private Delegate Function GetControlTextInvoker(ByVal ctl As Control) As String
Private Function GetControlText(ByVal ctl As Control) As String
Dim text As String
If ctl.InvokeRequired Then
text = CStr(ctl.Invoke(New GetControlTextInvoker(AddressOf GetControlText), _
ctl))
Else
text = ctl.Text
End If
Return text
End Function
Следуйте самым простым (на мой взгляд) способом изменения объектов из другого потока:
using System.Threading.Tasks;
using System.Threading;
namespace TESTE
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Action<string> DelegateTeste_ModifyText = THREAD_MOD;
Invoke(DelegateTeste_ModifyText, "MODIFY BY THREAD");
}
private void THREAD_MOD(string teste)
{
textBox1.Text = teste;
}
}
}
control.BeginInvoke
работать тоже? – newbieguy 11 December 2016 в 00:30