我正在WinRt中使用C#和SQLite從Windows應用程序調用WinRt類庫...對象在意外的時間返回空引用錯誤...WinRt C#空異常 - 使用IAsyncOperationWithProgress的對象範圍問題
我試圖執行登錄服務,通過檢查數據文件是否存在來檢查當前用戶是否已登錄,然後檢查用戶是否是當前登錄用戶...
用戶只需輸入他們的ID並點擊登錄按鈕即可。它創建一個包裝SQLite數據庫的DataService對象,然後「注入」UserStartupService。
UserStartupService使用依賴注入,單例並實現IDisposable。
問題1)如果用戶第二次單擊登錄按鈕,UserStartupService對象構造函數不會運行,並且在使用內部對象時,即使它在退出using塊後通過dispose方法運行,它們仍會拋出null引用錯誤,這迫使我停用登錄按鈕,這是一個最好的解決方案。新用戶必須退出程序才能以新用戶身份登錄。 (原始代碼沒有實現IAsyncOperationWithProgress,但這應該沒關係......)
問題2)我現在試圖實現IAsyncOperationWithProgress將進度中繼到UI,並且它立即獲得null引用錯誤嘗試使用_dataFeedService就行:
var json = await _dataFeedService.ValidateUser(userId);
即使它運行在using語句的頂部構造預期...
我覺得這是我失蹤這裏範圍/線程問題。也許一些明顯的...
任何想法?謝謝!
// logon button pressed...
private void LogOn_Click(object sender, RoutedEventArgs e)
{
// Create database service for DI
DataService _dataService = new DataService("MyData.sqlite");
// using statement for scope control
using (UserStartupService uss = UserStartupService.GetInstance(_dataService))
{
// progress bar...
CurrentProgress.Visibility = Windows.UI.Xaml.Visibility.Visible;
// create op and call...
IAsyncOperationWithProgress<string, int> op;
op = uss.SetUpUser(txtUserId.Text);
op.Progress = (info, progress) =>
{
CurrentProgress.Value = progress;
};
op.Completed = (info, status) =>
{
var results = info.GetResults();
// when completed...
if (status == AsyncStatus.Completed)
{
txtMessage.Text = "Current user data already loaded...";
CurrentProgress.Value = 100;
} // if cancelled...
else if (status == AsyncStatus.Canceled)
{
// Operation canceled - not implemented...
}
};
}
btnLogon.IsEnabled = false;
}
public sealed class UserStartupService : IDisposable
{
#region properties
// services
private static DataService _dataService;
private static DataFeedService _dataFeedService;
private static SqliteService _sqlMAFService;
private static SerialiseDeserialiseService _serializeService;
private string _token = String.Empty;
#endregion properties
#region constructors with DI and singleton pattern
// use this code to implement singleton patter...
// private constructor = can't instance without GetInstance...
private UserStartupService(DataService dataService)
{
// guard clause...
if (dataService == null)
{
throw new ArgumentNullException("DataService");
}
_dataService = dataService;
_dataFeedService = new DataFeedService();
_sqlMAFService = new SqliteService(_dataService);
_serializeService = new SerialiseDeserialiseService();
}
// implement singleton
public static UserStartupService GetInstance(DataService dataService)
{
_dataService = dataService;
return MyNestedSingletonClass.singleton;
}
class MyNestedSingletonClass
{
internal static readonly UserStartupService singleton = new UserStartupService(_dataService);
static MyNestedSingletonClass() { }
}
#endregion constructors with DI and singleton pattern
public IAsyncOperationWithProgress<string, int> SetUpUser(string userId)
{
return AsyncInfo.Run<string, int>((token, progress) =>
Task.Run<string>(async() =>
{
progress.Report(1);
try
{
// validate user against server REST feed and get token
var json = await _dataFeedService.ValidateUser(userId);
// ... it never gets here due to _dataFeedService null exception
// ...more code ... never gets here...
}
catch (Exception ex)
{
return ex.Message;
}
progress.Report(100);
return "";
}, token));
}
#region implement IDisposable
public void Dispose()
{
_serializeService = null;
_sqlMAFService.Dispose();
_sqlMAFService = null;
_dataFeedService.Dispose();
_dataFeedService = null;
_dataService.CloseConnection();
_dataService = null;
}
#endregion implement IDisposable
}
THX快速回復。對處置的好建議。我正在實施你的建議,看看它的其餘部分如何。我會告訴你。 – CodeChops