我正在構建一個半自動管理平臺來跟蹤我的日間交易。使用 python 腳本,我可以從平臺獲取資訊,并通過管道將資訊傳遞給將其傳遞到SQLite資料庫的應用程式。
現在我正在將資料從資料庫中取出并放入應用程式的 GUI 中。現在,所有 3 個方法都在一個Task執行緒上運行,因為管道服務器正在使用無限 while 回圈以及從資料庫獲取資料的方法。由于資料每 2 秒更改一次,因此它也必須更新 GUI 中的資料。
從 xaml 系結到模型不起作用,因為該方法在不同的執行緒上運行。這就是我卡住的地方。
代碼如下,
頁面的第一個方法是ObservableCollection和初始化,它啟動Task方法和Task.Run();方法PropertyChanged。
private ObservableCollection<OpenTradesModel> _trades = new ObservableCollection<OpenTradesModel>();
public ObservableCollection<OpenTradesModel> Trades
{
get { return _trades; }
set { _trades = value; OnPropertyChanged(nameof(Trades)); Debug.Print("Property Changed!"); }
}
public OpenTradesView()
{
InitializeComponent();
List<Task> tasks = new()
{
Task.Run(() => { startServerAndUseData(); }),
Task.Run(() => { runScript(); }),
Task.Run(() => { DataBaseQueryToGUI(); }),
};
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
以下方法從SQLite資料庫中獲取資料并將其放入_trades.
public Task DataBaseQueryToGUI()
{
while (true)
{
try
{
using var db = new DatabaseContext();
var rowData = db.OpenTrades.OrderBy(x => x.Id).ToList();
foreach (var row in rowData)
{
var query = new OpenTradesModel()
{
Ticket = row.Ticket,
Time = row.Time,
Type = row.Type,
Magic = row.Magic,
Identifier = row.Identifier,
Reason = row.Reason,
Volume = row.Volume,
PriceOpen = row.PriceOpen,
StopLoss = row.StopLoss,
TakeProfit = row.TakeProfit,
CurrentPrice = row.CurrentPrice,
Swap = row.Swap,
Profit = row.Profit,
Symbol = row.Symbol,
};
_trades.Add(query); //This is where the exception is thrown.
Debug.Print("Added to Model!");
}
}
catch (Exception e)
{
Debug.Print(e.ToString());
break;
}
Thread.Sleep(2000);
}
return Task.CompletedTask;
}
xaml如下。
<ListView x:Name="ListData" MaxWidth="1496" Width="1496" Height="457" MaxHeight="457"
ItemsSource="{x:Bind Trades, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListViewHeaderItem Margin="-11,0,0,0">
...
</ListViewHeaderItem>
<ListView.ItemTemplate>
<DataTemplate>
<Expander>
<Expander.Header>
<Grid>
<Grid.ColumnDefinitions>
...
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Trades}"/>
<TextBlock Grid.Column="1" Text="{Binding Time}" Margin="-17,0,0,0"/>
<TextBlock Grid.Column="2" Text="{Binding Type}"/>
<TextBlock Grid.Column="3" Text="{Binding Magic}"/>
<TextBlock Grid.Column="4" Text="{Binding Identifier}"/>
<TextBlock Grid.Column="5" Text="{Binding Reason}"/>
<TextBlock Grid.Column="6" Text="{Binding Volume}"/>
<TextBlock Grid.Column="7" Text="{Binding PriceOpen}"/>
<TextBlock Grid.Column="8" Text="{Binding StopLoss}"/>
<TextBlock Grid.Column="9" Text="{Binding TakeProfit}"/>
<TextBlock Grid.Column="10" Text="{Binding CurrentPrice}"/>
<TextBlock Grid.Column="11" Text="{Binding Swap}" Margin="-15,0,0,0"/>
<TextBlock Grid.Column="12" Text="{Binding Profit}" Margin="15,0,0,0"/>
<TextBlock Grid.Column="13" Text="{Binding Symbol}"/>
</Grid>
</Expander.Header>
系結似乎有效,但不顯示放入_trades. 正如以下例外表明它與執行緒有關,我只是不知道如何將資料獲取到 UI 執行緒。我在這里找到的每個答案都不適合我。
System.Runtime.InteropServices.COMException (0x8001010E): The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD))
at WinRT.ExceptionHelpers.<ThrowExceptionForHR>g__Throw|20_0(Int32 hr)
at WinRT.ExceptionHelpers.ThrowExceptionForHR(Int32 hr)
at ABI.Microsoft.UI.Xaml.Interop.WinRTNotifyCollectionChangedEventArgsRuntimeClassFactory.CreateInstanceWithAllParameters(NotifyCollectionChangedAction action, IList newItems, IList oldItems, Int32 newIndex, Int32 oldIndex)
at ABI.System.Collections.Specialized.NotifyCollectionChangedEventArgs.CreateMarshaler2(NotifyCollectionChangedEventArgs value)
at ABI.System.Collections.Specialized.NotifyCollectionChangedEventHandler.NativeDelegateWrapper.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 index, T item)
at System.Collections.ObjectModel.Collection`1.Add(T item)
at TradeAdministration.Views.OpenTradesView.DataBaseQueryToGUI() in C:\Users\Nick\source\repos\TradeAdministration\TradeAdministration\Views\OpenTradesView.xaml.cs:line 96
希望你們中的一個能讓我走上正確的思路。提前致謝!
uj5u.com熱心網友回復:
DataBaseQueryToGUI()我通過如下更改函式來修復它:
private async void DataBaseQueryToGUI() // Made it an async method.
{
await Task.Run(() => // Added
{
while (true)
{
try
{
using var db = new DatabaseContext();
var rowData = db.OpenTrades.OrderBy(x => x.Id).ToList();
foreach (var row in rowData)
{
var query = new OpenTradesModel()
{
Ticket = row.Ticket,
Time = row.Time,
Type = row.Type,
Magic = row.Magic,
Identifier = row.Identifier,
Reason = row.Reason,
Volume = row.Volume,
PriceOpen = row.PriceOpen,
StopLoss = row.StopLoss,
TakeProfit = row.TakeProfit,
CurrentPrice = row.CurrentPrice,
Swap = row.Swap,
Profit = row.Profit,
Symbol = row.Symbol,
};
this.DispatcherQueue.TryEnqueue(() => // Pushed these to the Dispatcher.
{
_trades.Add(query);
Debug.Print("Added to Model!");
});
}
}
catch (Exception e)
{
Debug.Print(e.ToString());
break;
}
Thread.Sleep(2000);
}
});
}
這暫時有效。雖然我遺漏了一些資料,但這是可以修復的。現在我需要想辦法更新資料而不是添加新資料。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/485887.html
