我目前有一个 dotnet 5.0 Worker Service 项目,该项目托管一个后台服务,该服务定期执行业务线流程。我设法通过在CreateHostBuilder方法内设置主机来摸索,并且这一切都作为 docker 容器内的可执行文件运行良好。
但是,我现在想添加一个 HTTP api / ui,以便我可以公开一个“健康”端点和一些漂亮的网页,这些网页访问与后台服务相同的进程内内存,以执行诸如显示 in 的内容之类的操作。 -内存缓存、逐出缓存条目、手动触发业务流程的运行等,我完全迷失了。
我想我只是以某种方式在绑定ConfigureServices到我指定的端口上的 ASPNET razor 项目中定义的类的方法中配置一个额外的托管服务,但经过几次尝试后,我有点困惑如何开始解决这个问题,更不用说让它真正发挥作用:-(。
具体来说,我有一个如下所示的 C# 项目:
我的Worker.csproj
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="4.0.0-dev-00051" />
<PackageReference Include="Serilog.Formatting.Compact" Version="1.1.1-dev-00940" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0-dev-00839" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MyAppCode\MyAppCode.csproj" />
</ItemGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)
和一个如下所示的Program.cs :
public static void Main(string[] args)
{
Program.InitSerilog();
Program.CreateHostBuilder(args).Build().Run();
}
public static void InitSerilog()
{
... do …Run Code Online (Sandbox Code Playgroud) 我正在使用MVVM模式开发WPF应用程序.
该应用程序从服务器加载验证码图像,并在准备好时将其分配给WPF表单上的图像.我正在使用BackgroundWorker为我做线程,如下所示:
加载Window时,会调用以下内容:
BackgroundWorker _bgWorker = new BackgroundWorker();
_bgWorker.DoWork += GetCaptchaImage;
_bgWorker.RunWorkerAsync();
Run Code Online (Sandbox Code Playgroud)
GetCaptchaImage函数非常简单,在另一个线程中加载图像:
BitmapSource _tempBitmap = GetCaptchaFromServer();
Run Code Online (Sandbox Code Playgroud)
我需要知道如何调用Dispatcher将此ImageSource分配给我的Window的图像源,目前我在加载_tempBitmap之后调用调度程序,如下所示:
Application.Current.Dispatcher.Invoke(
new Action(() => CaptchaBitmap = _tempBitmap));
Run Code Online (Sandbox Code Playgroud)
CaptchaBitmap数据绑定到我的图像源.
但是,当我这样做时,抛出InvalidOperationException,并且对_tempBitmap的任何引用都会在GUI线程中返回错误.我知道它是因为我在调度程序GUI线程中访问它,当它在BackgroundWorker线程中创建时,但我该如何解决它?
非常感谢帮助!:)
我正在创建一个应用程序.我正在扫描驱动器的文件以搜索特定模式我的进度条正在更新,最后所有文件名都列在列表框中.我想要立即列出所有这些文件一旦发现它们包含图案.
我正在使用BackgroundWorker
我已经使用了BackgroundWorkers了,但我以前从未遇到过这个问题.我的程序分析逻辑分析仪的输出,产生数据包,其中有数千个.为了防止更新延迟更新我的表单中的ListView(我之前报告了每个发现的,并且表单完全没有响应)我正在收集通用列表(List <Packet>)中的BackgroundWorker内的数据包和然后报告当找到n量(当前为250),或者发生异常时,或者当它完成时.
当我在List <Packet>上进行迭代时,问题发生在我的回调中,我得到一个InvalidOperationException,其中包含"Collection was modified"错误.我没有触及foreach中的集合(我正在添加到另一个集合中,但我认为没有理由可以修改我正在迭代的集合 - 再加上评论它不能解决问题.)我是甚至尝试锁定e.UserState,将e.UserState存储到本地作用域List <Packet>并锁定,似乎没有任何作用.
这是我的回调方法的代码:
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
packetsListView.SuspendLayout();
lock ((List<Packet>)e.UserState)
{
foreach (Packet packet in (List<Packet>)e.UserState)
{
packets.Add(packet);
ListViewItem item = new ListViewItem(string.Format("{0}ns", Math.Round(packet.StartSampleNumber * 41.666667)));
item.Tag = packet;
item.SubItems.Add(new ListViewItem.ListViewSubItem(item, packet.Description));
packetsListView.Items.Add(item);
}
}
packetsListView.ResumeLayout();
statusLabel.Text = string.Format("Analyzing...found {0} {1}", packetsListView.Items.Count, packetsListView.Items.Count == 1 ? "packet" : "packets");
}
Run Code Online (Sandbox Code Playgroud) 我有这样的感觉.它给了我错误.我删除了所有不需要的代码部分.它给了我这个错误
The calling thread cannot access this object because a different thread owns it.
Run Code Online (Sandbox Code Playgroud)
public partial class MainWindow : Window
{
BackgroundWorker worker;
Grafik MainGrafik;
double ProgressBar
{
set { this.progressBarMain.Value = value; }
}
public MainWindow()
{
InitializeComponent();
worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
MainGrafik = new Grafik();
MainGrafik.ProgressUpdate +=
new Grafik.ProgressUpdateDelegate(MainGrafik_ProgressUpdate);
worker.RunWorkerAsync();
}
void MainGrafik_ProgressUpdate(double progress)
{
ProgressBar = progress;
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
while(true)
{
MainGrafik.Refresh();
Thread.Sleep(2000);
}
}
}
Run Code Online (Sandbox Code Playgroud)
class Grafik …Run Code Online (Sandbox Code Playgroud) 我希望我的后台工作人员报告单个任务和总进度的进度.有什么建议我如何得到多个值到backgroundworker_ProgressChanged?
谢谢
我有日志拖尾应用程序,它在不定式循环中执行后台工作程序线程并检查某些TXT文件中的最新条目.一旦找到新条目,我使用Dispatcher.Invoke更新屏幕上的TextBox,并将最新条目添加到文本文件中.
问题是,如果源文本文件每毫秒不断更新,用户界面就会冻结,因为Dispatcher.Invoke经常更新文本框.
不知道是否有任何解决方法.我可以从文本文件中获取更大的块但不想破坏日志拖尾的实时体验,也不想延迟通过UI线程将行写入TextBox,因为这会使我的应用程序与实际数据不同步源文本文件.
这是后台工作者的DoWork方法
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
reader = new StreamReader(new FileStream(file.File, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
lastMaxOffset = reader.BaseStream.Length;
while (true)
{
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
if (reader.BaseStream.Length == lastMaxOffset)
continue;
reader.BaseStream.Seek(lastMaxOffset, SeekOrigin.Begin);
string line = "";
while ((line = reader.ReadLine()) != null)
this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, (Action)(() =>
{
textLog.Text += "\r" + line;
scrollViewer.ScrollToBottom();
}));
lastMaxOffset = reader.BaseStream.Position;
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,UI线程只是简单地将文本附加到TextBox,并且当它经常发生接口冻结时
我有ObjectContext.SaveChanges方法的问题:
public void Save(Action<object, object> action)
{
EventAggregator.GetEvent<EntityServiceRequestingEvent>().Publish(true);
var bw = new BackgroundWorker();
var saved = false;
bw.DoWork += (o, ee) =>
{
ProgramStatusService.Status = Resources.DatabaseSavingMessage;
if (!CanSave())
{
throw new InvalidOperationException(
"You must not call Save when CanSave returns false.");
}
try
{
lock (Context)
{
Context.SaveChanges();
saved = true;
}
}
catch (ValidationException e)
{
MessageService.ShowError(null, string.Format(CultureInfo.CurrentCulture,
Resources.SaveErrorInvalidEntities,
e.Message));
}
catch (UpdateException e)
{
var innerException = e.InnerException as SqlException;
if (innerException != null && innerException.Number == 2601) …Run Code Online (Sandbox Code Playgroud) 在我的应用程序中我使用backgroundWorker,在一些TextBox中设置文本,我首先需要调用TextBox.
首先我使用:
if (someTextBox.InvokeRequired)
{
someTextBox.Invoke((MethodInvoker)delegate
{
someTextBox.Text = "some_text";
});
}
else
{
someTextBox.Text = "some_text";
}
Run Code Online (Sandbox Code Playgroud)
这个方法对我很好,但因为我有多个TextBox-es我写道:
private void invComp(TextBox txtBox, String str)
{
if (txtBox.InvokeRequired)
{
txtBox.Invoke((MethodInvoker)delegate
{
txtBox.Text = str;
});
}
else
{
txtBox.Text = str;
}
}
Run Code Online (Sandbox Code Playgroud)
最好以这种方式调用它?(invComp(someTextBox,"some_text");或者我可能有第三种,更好的方式?
我调用了一些按钮,我想在按钮上写这样的东西,如果这样可以吗?
TNX
从另一个线程更新UI这两种方法中哪一种更好?(对我来说,他们都工作,但哪个更安全?)我更喜欢SetPropertyThreadSafe方法,因为它需要更少的代码.
1.
label1.SetPropertyThreadSafe(() => this.label1.Text, "New Value");
Run Code Online (Sandbox Code Playgroud)
2.
if (label1.InvokeRequired)
{
label1.Invoke(new MethodInvoker(delegate {
label1.Text="New Value"; }));
}
Run Code Online (Sandbox Code Playgroud) backgroundworker ×10
c# ×7
wpf ×3
.net ×2
invoke ×2
.net-core ×1
asp.net-core ×1
collections ×1
dispatcher ×1
events ×1
generic-list ×1
mvvm ×1
textbox ×1
winforms ×1